Merge branch 'main' into buf-breaking

pull/17513/head
Mike Kruskal 8 months ago committed by GitHub
commit cd46bb2c1e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      .github/workflows/test_cpp.yml
  2. 14
      .github/workflows/test_java.yml
  3. 3
      .github/workflows/test_objectivec.yml
  4. 9
      MODULE.bazel
  5. 6
      WORKSPACE
  6. 1
      bazel/BUILD.bazel
  7. 33
      bazel/private/BUILD.bazel
  8. 35
      bazel/private/native_bool_flag.bzl
  9. 357
      bazel/private/proto_library_rule.bzl
  10. 8
      bazel/private/proto_toolchain_rule.bzl
  11. 2
      bazel/private/toolchain_helpers.bzl
  12. 21
      bazel/proto_library.bzl
  13. 12
      bazel/py_proto_library.bzl
  14. 1
      bazel/toolchains/BUILD.bazel
  15. 3
      bazel/toolchains/proto_toolchain.bzl
  16. 1
      build_defs/cpp_opts.bzl
  17. 7
      conformance/BUILD.bazel
  18. 115
      conformance/binary_json_conformance_suite.cc
  19. 11
      conformance/conformance.proto
  20. 12
      conformance/conformance_cpp.cc
  21. 40
      conformance/conformance_python.py
  22. 57
      conformance/conformance_rust.rs
  23. 310
      conformance/conformance_test.cc
  24. 92
      conformance/conformance_test.h
  25. 150
      conformance/conformance_test_runner.cc
  26. 204
      conformance/failure_list_cpp.txt
  27. 292
      conformance/failure_list_java.txt
  28. 16
      conformance/failure_list_java_lite.txt
  29. 8
      conformance/failure_list_objc.txt
  30. 38
      conformance/text_format_conformance_suite.cc
  31. 82
      conformance/text_format_failure_list_cpp.txt
  32. 40
      conformance/text_format_failure_list_java.txt
  33. 194
      conformance/text_format_failure_list_python.txt
  34. 144
      conformance/text_format_failure_list_python_cpp.txt
  35. 144
      conformance/text_format_failure_list_python_upb.txt
  36. 42
      conformance/update_failure_list.py
  37. 333
      csharp/src/Google.Protobuf.Conformance/Conformance.pb.cs
  38. 6
      editions/generated_files_test.cc
  39. 4
      editions/golden/compare_cpp_codegen_failure.txt
  40. 4
      editions/golden/compare_cpp_codegen_failure.xml
  41. 2
      hpb/BUILD
  42. 10
      hpb/extension_lock_test.cc
  43. 8
      hpb/hpb.cc
  44. 346
      hpb/hpb.h
  45. 25
      hpb/repeated_field.h
  46. 6
      hpb/repeated_field_iterator.h
  47. 2
      hpb_generator/BUILD
  48. 19
      hpb_generator/gen_accessors.cc
  49. 4
      hpb_generator/gen_extensions.cc
  50. 69
      hpb_generator/gen_messages.cc
  51. 24
      hpb_generator/gen_repeated_fields.cc
  52. 5
      hpb_generator/names.cc
  53. 3
      hpb_generator/tests/BUILD
  54. 263
      hpb_generator/tests/test_generated.cc
  55. 3
      java/core/src/main/java/com/google/protobuf/ArrayDecoders.java
  56. 5
      java/core/src/main/java/com/google/protobuf/ByteString.java
  57. 2
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  58. 27
      java/core/src/main/java/com/google/protobuf/FieldSet.java
  59. 12
      java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
  60. 2
      java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java
  61. 3
      java/core/src/main/java/com/google/protobuf/MessageSchema.java
  62. 1
      java/core/src/main/java/com/google/protobuf/MessageSetSchema.java
  63. 6
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  64. 3
      java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java
  65. 60
      java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
  66. 1
      java/kotlin/BUILD.bazel
  67. 13
      java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
  68. 3
      java/lite/src/test/java/com/google/protobuf/LiteTest.java
  69. 3
      java/util/src/main/java/com/google/protobuf/util/JsonFormat.java
  70. 81
      objectivec/GPBCodedInputStream.m
  71. 4
      objectivec/GPBCodedInputStream_PackagePrivate.h
  72. 20
      objectivec/GPBMessage.m
  73. 3
      objectivec/GPBMessage_PackagePrivate.h
  74. 3
      objectivec/GPBUnknownFieldSet.m
  75. 19
      objectivec/GPBUnknownFields.m
  76. 4
      objectivec/GPBUtilities.h
  77. 84
      objectivec/GPBUtilities.m
  78. 143
      objectivec/Tests/GPBCodedInputStreamTests.m
  79. 17
      objectivec/Tests/GPBMessageTests+Serialization.m
  80. 107
      objectivec/Tests/GPBMessageTests.m
  81. 179
      objectivec/Tests/GPBUnknownFieldSetTest.m
  82. 159
      objectivec/Tests/GPBUnknownFieldsTest.m
  83. 93
      objectivec/Tests/GPBUtilitiesTests.m
  84. 31
      objectivec/Tests/unittest_objc.proto
  85. 21
      protobuf_deps.bzl
  86. 185
      protos/protos.cc
  87. 29
      protos/protos.h
  88. 28
      python/google/protobuf/internal/any_test.proto
  89. 2
      python/google/protobuf/internal/api_implementation.cc
  90. 2
      python/google/protobuf/internal/descriptor_pool_test.py
  91. 2
      python/google/protobuf/internal/message_factory_test.py
  92. 7
      python/google/protobuf/internal/more_messages.proto
  93. 9
      python/google/protobuf/internal/python_message.py
  94. 5
      python/google/protobuf/internal/symbol_database_test.py
  95. 2
      python/google/protobuf/internal/text_format_test.py
  96. 29
      python/google/protobuf/internal/well_known_types_test.proto
  97. 76
      python/google/protobuf/internal/well_known_types_test.py
  98. 2
      python/google/protobuf/pyext/cpp_message.py
  99. 78
      rust/BUILD
  100. 28
      rust/cargo/Cargo.toml
  101. Some files were not shown because too many files have changed in this diff Show More

@ -31,19 +31,19 @@ jobs:
# Override cases with custom images # Override cases with custom images
- config: { name: "Bazel7", flags: --noenable_bzlmod } - config: { name: "Bazel7", flags: --noenable_bzlmod }
version: Bazel7 cache_key: Bazel7
image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e" image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e"
targets: "//src/... //third_party/utf8_range/..." targets: "//src/... //third_party/utf8_range/..."
- config: { name: "Bazel7 with Bzlmod", flags: --enable_bzlmod --enable_workspace } - config: { name: "Bazel7 with Bzlmod", flags: --enable_bzlmod --enable_workspace }
version: Bazel7bzlmod cache_key: Bazel7bzlmod
image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e" image: "us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e"
targets: "//src/... //third_party/utf8_range/..." targets: "//src/... //third_party/utf8_range/..."
- config: { name: "TCMalloc" } - config: { name: "TCMalloc" }
version: TcMalloc cache_key: TcMalloc
image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:1c5133455481f4d1bb8afa477029604f41f1a3c46cebe4d9958cf1af95b5c87c" image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/tcmalloc@sha256:1c5133455481f4d1bb8afa477029604f41f1a3c46cebe4d9958cf1af95b5c87c"
targets: "//src/... //third_party/utf8_range/..." targets: "//src/... //third_party/utf8_range/..."
- config: { name: "aarch64" } - config: { name: "aarch64" }
version: TcMalloc cache_key: TcMalloc
targets: "//src/... //src/google/protobuf/compiler:protoc_aarch64_test //third_party/utf8_range/..." targets: "//src/... //src/google/protobuf/compiler:protoc_aarch64_test //third_party/utf8_range/..."
image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:6.3.0-aarch64-68e662b3a56b881804dc4e9d45f949791cbc4b94" image: "us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:6.3.0-aarch64-68e662b3a56b881804dc4e9d45f949791cbc4b94"
name: Linux ${{ matrix.config.name }} name: Linux ${{ matrix.config.name }}
@ -58,7 +58,7 @@ jobs:
with: with:
image: ${{ matrix.image }} image: ${{ matrix.image }}
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: cpp_linux/${{ matrix.version }} bazel-cache: cpp_linux/${{ matrix.cache_key }}
bazel: test ${{ matrix.targets }} ${{ matrix.config.flags }} bazel: test ${{ matrix.targets }} ${{ matrix.config.flags }}
exclude-targets: ${{ matrix.exclude-targets }} exclude-targets: ${{ matrix.exclude-targets }}

@ -18,31 +18,31 @@ jobs:
matrix: matrix:
include: include:
- name: OpenJDK 8 - name: OpenJDK 8
version: '8' cache_key: '8'
image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:8-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:8-1fdbb997433cb22c1e49ef75ad374a8d6bb88702
# TODO: b/318555165 - enable the layering check. Currently it does # TODO: b/318555165 - enable the layering check. Currently it does
# not work correctly with the toolchain in this Docker image. # not work correctly with the toolchain in this Docker image.
targets: //java/... //java/internal:java_version //compatibility/... --features=-layering_check targets: //java/... //java/internal:java_version //compatibility/... --features=-layering_check
- name: OpenJDK 11 - name: OpenJDK 11
version: '11' cache_key: '11'
image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:11-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:11-1fdbb997433cb22c1e49ef75ad374a8d6bb88702
targets: //java/... //java/internal:java_version //compatibility/... targets: //java/... //java/internal:java_version //compatibility/...
- name: OpenJDK 17 - name: OpenJDK 17
version: '17' cache_key: '17'
image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:17-1fdbb997433cb22c1e49ef75ad374a8d6bb88702 image: us-docker.pkg.dev/protobuf-build/containers/test/linux/java:17-1fdbb997433cb22c1e49ef75ad374a8d6bb88702
targets: //java/... //java/internal:java_version //compatibility/... targets: //java/... //java/internal:java_version //compatibility/...
- name: Bazel7 - name: Bazel7
version: 'bazel7nobzlmod' cache_key: 'bazel7nobzlmod'
image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e
targets: //java/... //java/internal:java_version //compatibility/... targets: //java/... //java/internal:java_version //compatibility/...
flags: --noenable_bzlmod flags: --noenable_bzlmod
- name: Bazel7 with Bzlmod - name: Bazel7 with Bzlmod
version: 'bazel7bzlmod' cache_key: 'bazel7bzlmod'
image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e image: us-docker.pkg.dev/protobuf-build/containers/common/linux/bazel:7.1.2-cf84e92285ca133b9c8104ad7b14d70e953cbb8e
targets: //java/... //java/internal:java_version //compatibility/... targets: //java/... //java/internal:java_version //compatibility/...
flags: --enable_bzlmod --enable_workspace flags: --enable_bzlmod --enable_workspace
- name: aarch64 - name: aarch64
version: 'aarch64' cache_key: 'aarch64'
image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17 image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:aarch64-63dd26c0c7a808d92673a3e52e848189d4ab0f17
targets: //java/... //compatibility/... //src/google/protobuf/compiler:protoc_aarch64_test targets: //java/... //compatibility/... //src/google/protobuf/compiler:protoc_aarch64_test
@ -58,7 +58,7 @@ jobs:
with: with:
image: ${{ matrix.image }} image: ${{ matrix.image }}
credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
bazel-cache: java_linux/${{ matrix.version }} bazel-cache: java_linux/${{ matrix.cache_key }}
bazel: test ${{ matrix.targets }} ${{ matrix.flags }} --test_env=KOKORO_JAVA_VERSION bazel: test ${{ matrix.targets }} ${{ matrix.flags }} --test_env=KOKORO_JAVA_VERSION
# TODO restore this test (or a better one) when gRPC has rebuilt with 26.x # TODO restore this test (or a better one) when gRPC has rebuilt with 26.x

@ -57,8 +57,7 @@ jobs:
-scheme ProtocolBuffers \ -scheme ProtocolBuffers \
-configuration ${{ matrix.xc_config }} \ -configuration ${{ matrix.xc_config }} \
-destination "${{ matrix.destination }}" \ -destination "${{ matrix.destination }}" \
test \ test
| xcpretty
- name: Report ccache stats - name: Report ccache stats
shell: bash shell: bash

@ -13,7 +13,7 @@ module(
# https://bazel.build/versions/6.0.0/build/bzlmod#version-resolution # https://bazel.build/versions/6.0.0/build/bzlmod#version-resolution
# Thus the highest version in their module graph is resolved. # Thus the highest version in their module graph is resolved.
bazel_dep(name = "abseil-cpp", version = "20230802.0.bcr.1", repo_name = "com_google_absl") bazel_dep(name = "abseil-cpp", version = "20230802.0.bcr.1", repo_name = "com_google_absl")
bazel_dep(name = "bazel_skylib", version = "1.4.1") bazel_dep(name = "bazel_skylib", version = "1.7.0")
bazel_dep(name = "jsoncpp", version = "1.9.5") bazel_dep(name = "jsoncpp", version = "1.9.5")
bazel_dep(name = "rules_cc", version = "0.0.9") bazel_dep(name = "rules_cc", version = "0.0.9")
bazel_dep(name = "rules_fuzzing", version = "0.5.2") bazel_dep(name = "rules_fuzzing", version = "0.5.2")
@ -27,9 +27,6 @@ bazel_dep(name = "platforms", version = "0.0.8")
bazel_dep(name = "zlib", version = "1.3.1") bazel_dep(name = "zlib", version = "1.3.1")
bazel_dep(name = "bazel_features", version = "1.13.0", repo_name = "proto_bazel_features") bazel_dep(name = "bazel_features", version = "1.13.0", repo_name = "proto_bazel_features")
# TODO: remove after toolchain types are moved to protobuf
bazel_dep(name = "rules_proto", version = "4.0.0")
SUPPORTED_PYTHON_VERSIONS = [ SUPPORTED_PYTHON_VERSIONS = [
"3.8", "3.8",
"3.9", "3.9",
@ -98,5 +95,7 @@ use_repo(maven, "maven")
# Development dependencies # Development dependencies
bazel_dep(name = "googletest", version = "1.14.0", repo_name = "com_google_googletest", dev_dependency = True) bazel_dep(name = "googletest", version = "1.14.0", repo_name = "com_google_googletest", dev_dependency = True)
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
bazel_dep(name = "rules_buf", version = "0.3.0", dev_dependency = True) bazel_dep(name = "rules_buf", version = "0.3.0", dev_dependency = True)
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
# rules_proto are needed for @com_google_protobuf_v25.0 used in //compatibility/... tests
bazel_dep(name = "rules_proto", version = "4.0.0", dev_dependency = True)

@ -41,10 +41,10 @@ http_archive(
http_archive( http_archive(
name = "com_google_googletest", name = "com_google_googletest",
sha256 = "730215d76eace9dd49bf74ce044e8daa065d175f1ac891cc1d6bb184ef94e565", sha256 = "7315acb6bf10e99f332c8a43f00d5fbb1ee6ca48c52f6b936991b216c586aaad",
strip_prefix = "googletest-f53219cdcb7b084ef57414efea92ee5b71989558", strip_prefix = "googletest-1.15.0",
urls = [ urls = [
"https://github.com/google/googletest/archive/f53219cdcb7b084ef57414efea92ee5b71989558.tar.gz" # 2023-03-16 "https://github.com/google/googletest/releases/download/v1.15.0/googletest-1.15.0.tar.gz" # 2024-07-15
], ],
) )

@ -40,6 +40,7 @@ bzl_library(
deps = [ deps = [
"//bazel/common:proto_common_bzl", "//bazel/common:proto_common_bzl",
"//bazel/common:proto_info_bzl", "//bazel/common:proto_info_bzl",
"//bazel/private:toolchain_helpers_bzl",
"@rules_python//python:py_info_bzl", "@rules_python//python:py_info_bzl",
], ],
) )

@ -6,9 +6,14 @@
# https://developers.google.com/open-source/licenses/bsd # https://developers.google.com/open-source/licenses/bsd
load("@bazel_skylib//:bzl_library.bzl", "bzl_library") load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("//bazel/private:native_bool_flag.bzl", "native_bool_flag")
licenses(["notice"]) licenses(["notice"])
toolchain_type(
name = "proto_toolchain_type",
)
bzl_library( bzl_library(
name = "upb_proto_library_internal_bzl", name = "upb_proto_library_internal_bzl",
srcs = [ srcs = [
@ -39,6 +44,11 @@ bzl_library(
"proto_toolchain_rule.bzl", "proto_toolchain_rule.bzl",
], ],
visibility = ["//bazel:__subpackages__"], visibility = ["//bazel:__subpackages__"],
deps = [
":toolchain_helpers_bzl",
"//bazel/common:proto_common_bzl",
"//bazel/common:proto_lang_toolchain_info_bzl",
],
) )
bzl_library( bzl_library(
@ -52,3 +62,26 @@ bzl_library(
"//bazel/common:proto_lang_toolchain_info_bzl", "//bazel/common:proto_lang_toolchain_info_bzl",
], ],
) )
native_bool_flag(
name = "experimental_proto_descriptor_sets_include_source_info",
flag = "experimental_proto_descriptor_sets_include_source_info",
match_value = "true",
visibility = ["//visibility:public"],
)
native_bool_flag(
name = "strict_proto_deps",
flag = "strict_proto_deps",
match_value = "off",
result = False,
visibility = ["//visibility:public"],
)
native_bool_flag(
name = "strict_public_imports",
flag = "strict_public_imports",
match_value = "off",
result = False,
visibility = ["//visibility:public"],
)

@ -0,0 +1,35 @@
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""
A helper rule that reads a native boolean flag.
"""
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
def _impl(ctx):
return [BuildSettingInfo(value = ctx.attr.value)]
_native_bool_flag_rule = rule(
implementation = _impl,
attrs = {"value": attr.bool()},
)
def native_bool_flag(*, name, flag, match_value = "true", result = True, **kwargs):
_native_bool_flag_rule(
name = name,
value = select({
name + "_setting": result,
"//conditions:default": not result,
}),
**kwargs
)
native.config_setting(
name = name + "_setting",
values = {flag: match_value},
visibility = ["//visibility:private"],
)

@ -0,0 +1,357 @@
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""
Implementation of proto_library rule.
"""
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@proto_bazel_features//:features.bzl", "bazel_features")
load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/common:proto_info.bzl", "ProtoInfo")
load("//bazel/private:toolchain_helpers.bzl", "toolchains")
STRICT_DEPS_FLAG_TEMPLATE = (
#
"--direct_dependencies_violation_msg=" +
"%%s is imported, but %s doesn't directly depend on a proto_library that 'srcs' it."
)
def _check_srcs_package(target_package, srcs):
"""Check that .proto files in sources are from the same package.
This is done to avoid clashes with the generated sources."""
#TODO: this does not work with filegroups that contain files that are not in the package
for src in srcs:
if target_package != src.label.package:
fail("Proto source with label '%s' must be in same package as consuming rule." % src.label)
def _get_import_prefix(ctx):
"""Gets and verifies import_prefix attribute if it is declared."""
import_prefix = ctx.attr.import_prefix
if not paths.is_normalized(import_prefix):
fail("should be normalized (without uplevel references or '.' path segments)", attr = "import_prefix")
if paths.is_absolute(import_prefix):
fail("should be a relative path", attr = "import_prefix")
return import_prefix
def _get_strip_import_prefix(ctx):
"""Gets and verifies strip_import_prefix."""
strip_import_prefix = ctx.attr.strip_import_prefix
if not paths.is_normalized(strip_import_prefix):
fail("should be normalized (without uplevel references or '.' path segments)", attr = "strip_import_prefix")
if paths.is_absolute(strip_import_prefix):
strip_import_prefix = strip_import_prefix[1:]
else: # Relative to current package
strip_import_prefix = _join(ctx.label.package, strip_import_prefix)
return strip_import_prefix.removesuffix("/")
def _proto_library_impl(ctx):
# Verifies attributes.
_check_srcs_package(ctx.label.package, ctx.attr.srcs)
srcs = ctx.files.srcs
deps = [dep[ProtoInfo] for dep in ctx.attr.deps]
exports = [dep[ProtoInfo] for dep in ctx.attr.exports]
import_prefix = _get_import_prefix(ctx)
strip_import_prefix = _get_strip_import_prefix(ctx)
check_for_reexport = deps + exports if not srcs else exports
_PackageSpecificationInfo = bazel_features.globals.PackageSpecificationInfo
for proto in check_for_reexport:
if getattr(proto, "allow_exports", None):
if not _PackageSpecificationInfo:
fail("Allowlist checks not supported before Bazel 6.4.0")
if not proto.allow_exports[_PackageSpecificationInfo].contains(ctx.label):
fail("proto_library '%s' can't be reexported in package '//%s'" % (proto.direct_descriptor_set.owner, ctx.label.package))
proto_path, virtual_srcs = _process_srcs(ctx, srcs, import_prefix, strip_import_prefix)
descriptor_set = ctx.actions.declare_file(ctx.label.name + "-descriptor-set.proto.bin")
proto_info = ProtoInfo(
srcs = virtual_srcs,
deps = deps,
descriptor_set = descriptor_set,
proto_path = proto_path,
workspace_root = ctx.label.workspace_root,
bin_dir = ctx.bin_dir.path,
allow_exports = ctx.attr.allow_exports,
)
_write_descriptor_set(ctx, proto_info, deps, exports, descriptor_set)
# We assume that the proto sources will not have conflicting artifacts
# with the same root relative path
data_runfiles = ctx.runfiles(
files = [proto_info.direct_descriptor_set],
transitive_files = depset(transitive = [proto_info.transitive_sources]),
)
return [
proto_info,
DefaultInfo(
files = depset([proto_info.direct_descriptor_set]),
default_runfiles = ctx.runfiles(), # empty
data_runfiles = data_runfiles,
),
]
def _process_srcs(ctx, srcs, import_prefix, strip_import_prefix):
"""Returns proto_path and sources, optionally symlinking them to _virtual_imports.
Returns:
(str, [File]) A pair of proto_path and virtual_sources.
"""
if import_prefix != "" or strip_import_prefix != "":
# Use virtual source roots
return _symlink_to_virtual_imports(ctx, srcs, import_prefix, strip_import_prefix)
else:
# No virtual source roots
return "", srcs
def _join(*path):
return "/".join([p for p in path if p != ""])
def _symlink_to_virtual_imports(ctx, srcs, import_prefix, strip_import_prefix):
"""Symlinks srcs to _virtual_imports.
Returns:
A pair proto_path, directs_sources.
"""
virtual_imports = _join("_virtual_imports", ctx.label.name)
proto_path = _join(ctx.label.package, virtual_imports)
if ctx.label.workspace_name == "":
full_strip_import_prefix = strip_import_prefix
else:
full_strip_import_prefix = _join("..", ctx.label.workspace_name, strip_import_prefix)
if full_strip_import_prefix:
full_strip_import_prefix += "/"
virtual_srcs = []
for src in srcs:
# Remove strip_import_prefix
if not src.short_path.startswith(full_strip_import_prefix):
fail(".proto file '%s' is not under the specified strip prefix '%s'" %
(src.short_path, full_strip_import_prefix))
import_path = src.short_path[len(full_strip_import_prefix):]
# Add import_prefix
virtual_src = ctx.actions.declare_file(_join(virtual_imports, import_prefix, import_path))
ctx.actions.symlink(
output = virtual_src,
target_file = src,
progress_message = "Symlinking virtual .proto sources for %{label}",
)
virtual_srcs.append(virtual_src)
return proto_path, virtual_srcs
def _write_descriptor_set(ctx, proto_info, deps, exports, descriptor_set):
"""Writes descriptor set."""
if proto_info.direct_sources == []:
ctx.actions.write(descriptor_set, "")
return
dependencies_descriptor_sets = depset(transitive = [dep.transitive_descriptor_sets for dep in deps])
args = ctx.actions.args()
if ctx.attr._experimental_proto_descriptor_sets_include_source_info[BuildSettingInfo].value:
args.add("--include_source_info")
if hasattr(ctx.attr, "_retain_options") and ctx.attr._retain_options:
args.add("--retain_options")
strict_deps = ctx.attr._strict_proto_deps[BuildSettingInfo].value
if strict_deps:
if proto_info.direct_sources:
strict_importable_sources = depset(
direct = proto_info._direct_proto_sources,
transitive = [dep._exported_sources for dep in deps],
)
else:
strict_importable_sources = None
if strict_importable_sources:
args.add_joined(
"--direct_dependencies",
strict_importable_sources,
map_each = proto_common.get_import_path,
join_with = ":",
)
# Example: `--direct_dependencies a.proto:b.proto`
else:
# The proto compiler requires an empty list to turn on strict deps checking
args.add("--direct_dependencies=")
# Set `-direct_dependencies_violation_msg=`
args.add(ctx.label, format = STRICT_DEPS_FLAG_TEMPLATE)
strict_imports = ctx.attr._strict_public_imports[BuildSettingInfo].value
if strict_imports:
public_import_protos = depset(transitive = [export._exported_sources for export in exports])
if not public_import_protos:
# This line is necessary to trigger the check.
args.add("--allowed_public_imports=")
else:
args.add_joined(
"--allowed_public_imports",
public_import_protos,
map_each = proto_common.get_import_path,
join_with = ":",
)
if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION:
toolchain = ctx.toolchains[toolchains.PROTO_TOOLCHAIN]
if not toolchain:
fail("Protocol compiler toolchain could not be resolved.")
proto_lang_toolchain_info = toolchain.proto
else:
proto_lang_toolchain_info = proto_common.ProtoLangToolchainInfo(
out_replacement_format_flag = "--descriptor_set_out=%s",
output_files = "single",
mnemonic = "GenProtoDescriptorSet",
progress_message = "Generating Descriptor Set proto_library %{label}",
proto_compiler = ctx.executable._proto_compiler,
protoc_opts = ctx.fragments.proto.experimental_protoc_opts,
plugin = None,
)
proto_common.compile(
ctx.actions,
proto_info,
proto_lang_toolchain_info,
generated_files = [descriptor_set],
additional_inputs = dependencies_descriptor_sets,
additional_args = args,
)
proto_library = rule(
_proto_library_impl,
# TODO: proto_common docs are missing
# TODO: ProtoInfo link doesn't work and docs are missing
doc = """
<p>If using Bazel, please load the rule from <a href="https://github.com/bazelbuild/rules_proto">
https://github.com/bazelbuild/rules_proto</a>.
<p>Use <code>proto_library</code> to define libraries of protocol buffers which
may be used from multiple languages. A <code>proto_library</code> may be listed
in the <code>deps</code> clause of supported rules, such as
<code>java_proto_library</code>.
<p>When compiled on the command-line, a <code>proto_library</code> creates a file
named <code>foo-descriptor-set.proto.bin</code>, which is the descriptor set for
the messages the rule srcs. The file is a serialized
<code>FileDescriptorSet</code>, which is described in
<a href="https://developers.google.com/protocol-buffers/docs/techniques#self-description">
https://developers.google.com/protocol-buffers/docs/techniques#self-description</a>.
<p>It only contains information about the <code>.proto</code> files directly
mentioned by a <code>proto_library</code> rule; the collection of transitive
descriptor sets is available through the
<code>[ProtoInfo].transitive_descriptor_sets</code> Starlark provider.
See documentation in <code>proto_info.bzl</code>.
<p>Recommended code organization:
<ul>
<li>One <code>proto_library</code> rule per <code>.proto</code> file.
<li>A file named <code>foo.proto</code> will be in a rule named <code>foo_proto</code>,
which is located in the same package.
<li>A <code>[language]_proto_library</code> that wraps a <code>proto_library</code>
named <code>foo_proto</code> should be called <code>foo_[language]_proto</code>,
and be located in the same package.
</ul>""",
attrs = {
"srcs": attr.label_list(
allow_files = [".proto", ".protodevel"],
flags = ["DIRECT_COMPILE_TIME_INPUT"],
# TODO: Should .protodevel be advertised or deprecated?
doc = """
The list of <code>.proto</code> and <code>.protodevel</code> files that are
processed to create the target. This is usually a non empty list. One usecase
where <code>srcs</code> can be empty is an <i>alias-library</i>. This is a
proto_library rule having one or more other proto_library in <code>deps</code>.
This pattern can be used to e.g. export a public api under a persistent name.""",
),
"deps": attr.label_list(
providers = [ProtoInfo],
doc = """
The list of other <code>proto_library</code> rules that the target depends upon.
A <code>proto_library</code> may only depend on other <code>proto_library</code>
targets. It may not depend on language-specific libraries.""",
),
"exports": attr.label_list(
providers = [ProtoInfo],
doc = """
List of proto_library targets that can be referenced via "import public" in the
proto source.
It's an error if you use "import public" but do not list the corresponding library
in the exports attribute.
Note that you have list the library both in deps and exports since not all
lang_proto_library implementations have been changed yet.""",
),
"strip_import_prefix": attr.string(
default = "/",
doc = """
The prefix to strip from the paths of the .proto files in this rule.
<p>When set, .proto source files in the <code>srcs</code> attribute of this rule are
accessible at their path with this prefix cut off.
<p>If it's a relative path (not starting with a slash), it's taken as a package-relative
one. If it's an absolute one, it's understood as a repository-relative path.
<p>The prefix in the <code>import_prefix</code> attribute is added after this prefix is
stripped.""",
),
"import_prefix": attr.string(
doc = """
The prefix to add to the paths of the .proto files in this rule.
<p>When set, the .proto source files in the <code>srcs</code> attribute of this rule are
accessible at is the value of this attribute prepended to their repository-relative path.
<p>The prefix in the <code>strip_import_prefix</code> attribute is removed before this
prefix is added.""",
),
"allow_exports": attr.label(
cfg = "exec",
providers = [bazel_features.globals.PackageSpecificationInfo] if bazel_features.globals.PackageSpecificationInfo else [],
doc = """
An optional allowlist that prevents proto library to be reexported or used in
lang_proto_library that is not in one of the listed packages.""",
),
"data": attr.label_list(
allow_files = True,
flags = ["SKIP_CONSTRAINTS_OVERRIDE"],
),
# buildifier: disable=attr-license (calling attr.license())
"licenses": attr.license() if hasattr(attr, "license") else attr.string_list(),
"_experimental_proto_descriptor_sets_include_source_info": attr.label(
default = "//bazel/private:experimental_proto_descriptor_sets_include_source_info",
),
"_strict_proto_deps": attr.label(
default =
"//bazel/private:strict_proto_deps",
),
"_strict_public_imports": attr.label(
default = "//bazel/private:strict_public_imports",
),
} | toolchains.if_legacy_toolchain({
"_proto_compiler": attr.label(
cfg = "exec",
executable = True,
allow_files = True,
default = configuration_field("proto", "proto_compiler"),
),
}), # buildifier: disable=attr-licenses (attribute called licenses)
fragments = ["proto"],
provides = [ProtoInfo],
toolchains = toolchains.use_toolchain(toolchains.PROTO_TOOLCHAIN),
)

@ -1,13 +1,9 @@
"""A Starlark implementation of the proto_toolchain rule.""" """A Starlark implementation of the proto_toolchain rule."""
load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo") load("//bazel/common:proto_lang_toolchain_info.bzl", "ProtoLangToolchainInfo")
load("//bazel/private:toolchain_helpers.bzl", "toolchains")
def _impl(ctx): def _impl(ctx):
kwargs = {}
if getattr(proto_common, "INCOMPATIBLE_PASS_TOOLCHAIN_TYPE", False):
kwargs["toolchain_type"] = "@rules_proto//proto:toolchain_type"
return [ return [
DefaultInfo( DefaultInfo(
files = depset(), files = depset(),
@ -23,7 +19,7 @@ def _impl(ctx):
protoc_opts = ctx.fragments.proto.experimental_protoc_opts, protoc_opts = ctx.fragments.proto.experimental_protoc_opts,
progress_message = ctx.attr.progress_message, progress_message = ctx.attr.progress_message,
mnemonic = ctx.attr.mnemonic, mnemonic = ctx.attr.mnemonic,
**kwargs toolchain_type = toolchains.PROTO_TOOLCHAIN,
), ),
), ),
] ]

@ -45,5 +45,5 @@ toolchains = struct(
find_toolchain = _find_toolchain, find_toolchain = _find_toolchain,
if_legacy_toolchain = _if_legacy_toolchain, if_legacy_toolchain = _if_legacy_toolchain,
INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION = _incompatible_toolchain_resolution, INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION = _incompatible_toolchain_resolution,
PROTO_TOOLCHAIN = "@rules_proto//proto:toolchain_type", PROTO_TOOLCHAIN = "//bazel/private:proto_toolchain_type",
) )

@ -1,3 +1,20 @@
"""proto_library rule""" # Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
"""
Macro of proto_library rule.
"""
proto_library = native.proto_library load("@proto_bazel_features//:features.bzl", "bazel_features")
load("//bazel/private:proto_library_rule.bzl", _proto_library = "proto_library")
def proto_library(**kwattrs):
# This condition causes Starlark rules to be used only on Bazel >=7.0.0
if bazel_features.proto.starlark_proto_info:
_proto_library(**kwattrs)
else:
# On older Bazel versions keep using native rules, so that mismatch in ProtoInfo doesn't happen
native.proto_library(**kwattrs)

@ -3,6 +3,7 @@
load("@rules_python//python:py_info.bzl", "PyInfo") load("@rules_python//python:py_info.bzl", "PyInfo")
load("//bazel/common:proto_common.bzl", "proto_common") load("//bazel/common:proto_common.bzl", "proto_common")
load("//bazel/common:proto_info.bzl", "ProtoInfo") load("//bazel/common:proto_info.bzl", "ProtoInfo")
load("//bazel/private:toolchain_helpers.bzl", "toolchains")
PY_PROTO_TOOLCHAIN = "@rules_python//python/proto:toolchain_type" PY_PROTO_TOOLCHAIN = "@rules_python//python/proto:toolchain_type"
@ -22,9 +23,6 @@ _PyProtoInfo = provider(
def _filter_provider(provider, *attrs): def _filter_provider(provider, *attrs):
return [dep[provider] for attr in attrs for dep in attr if provider in dep] return [dep[provider] for attr in attrs for dep in attr if provider in dep]
def _incompatible_toolchains_enabled():
return getattr(proto_common, "INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION", False)
def _py_proto_aspect_impl(target, ctx): def _py_proto_aspect_impl(target, ctx):
"""Generates and compiles Python code for a proto_library. """Generates and compiles Python code for a proto_library.
@ -51,7 +49,7 @@ def _py_proto_aspect_impl(target, ctx):
proto.path, proto.path,
)) ))
if _incompatible_toolchains_enabled(): if proto_common.INCOMPATIBLE_ENABLE_PROTO_TOOLCHAIN_RESOLUTION:
toolchain = ctx.toolchains[PY_PROTO_TOOLCHAIN] toolchain = ctx.toolchains[PY_PROTO_TOOLCHAIN]
if not toolchain: if not toolchain:
fail("No toolchains registered for '%s'." % PY_PROTO_TOOLCHAIN) fail("No toolchains registered for '%s'." % PY_PROTO_TOOLCHAIN)
@ -120,15 +118,15 @@ def _py_proto_aspect_impl(target, ctx):
_py_proto_aspect = aspect( _py_proto_aspect = aspect(
implementation = _py_proto_aspect_impl, implementation = _py_proto_aspect_impl,
attrs = {} if _incompatible_toolchains_enabled() else { attrs = toolchains.if_legacy_toolchain({
"_aspect_proto_toolchain": attr.label( "_aspect_proto_toolchain": attr.label(
default = "//python:python_toolchain", default = "//python:python_toolchain",
), ),
}, }),
attr_aspects = ["deps"], attr_aspects = ["deps"],
required_providers = [ProtoInfo], required_providers = [ProtoInfo],
provides = [_PyProtoInfo], provides = [_PyProtoInfo],
toolchains = [PY_PROTO_TOOLCHAIN] if _incompatible_toolchains_enabled() else [], toolchains = toolchains.use_toolchain(PY_PROTO_TOOLCHAIN),
) )
def _py_proto_library_rule(ctx): def _py_proto_library_rule(ctx):

@ -8,6 +8,7 @@ bzl_library(
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//bazel/private:proto_toolchain_rule_bzl", "//bazel/private:proto_toolchain_rule_bzl",
"//bazel/private:toolchain_helpers_bzl",
], ],
) )

@ -4,6 +4,7 @@ The macro additionally creates toolchain target when toolchain_type is given.
""" """
load("//bazel/private:proto_toolchain_rule.bzl", _proto_toolchain_rule = "proto_toolchain") load("//bazel/private:proto_toolchain_rule.bzl", _proto_toolchain_rule = "proto_toolchain")
load("//bazel/private:toolchain_helpers.bzl", "toolchains")
def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []): def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []):
"""Creates a proto_toolchain and toolchain target for proto_library. """Creates a proto_toolchain and toolchain target for proto_library.
@ -19,7 +20,7 @@ def proto_toolchain(*, name, proto_compiler, exec_compatible_with = []):
native.toolchain( native.toolchain(
name = name + "_toolchain", name = name + "_toolchain",
toolchain_type = "@rules_proto//proto:toolchain_type", toolchain_type = toolchains.PROTO_TOOLCHAIN,
exec_compatible_with = exec_compatible_with, exec_compatible_with = exec_compatible_with,
target_compatible_with = [], target_compatible_with = [],
toolchain = name, toolchain = name,

@ -15,7 +15,6 @@ COPTS = select({
"/wd4506", # no definition for inline function 'function' "/wd4506", # no definition for inline function 'function'
"/wd4800", # 'type' : forcing value to bool 'true' or 'false' (performance warning) "/wd4800", # 'type' : forcing value to bool 'true' or 'false' (performance warning)
"/wd4996", # The compiler encountered a deprecated declaration. "/wd4996", # The compiler encountered a deprecated declaration.
"/utf-8", # Set source and execution character sets to UTF-8
], ],
"//conditions:default": [ "//conditions:default": [
"-DHAVE_ZLIB", "-DHAVE_ZLIB",

@ -143,6 +143,7 @@ cc_library(
":conformance_cc_proto", ":conformance_cc_proto",
"//src/google/protobuf", "//src/google/protobuf",
"//src/google/protobuf:descriptor_legacy", "//src/google/protobuf:descriptor_legacy",
"//src/google/protobuf:endian",
"//src/google/protobuf:protobuf_lite", "//src/google/protobuf:protobuf_lite",
"//src/google/protobuf/util:differencer", "//src/google/protobuf/util:differencer",
"//src/google/protobuf/util:json_util", "//src/google/protobuf/util:json_util",
@ -232,6 +233,7 @@ cc_binary(
"//src/google/protobuf", "//src/google/protobuf",
"//src/google/protobuf:port", "//src/google/protobuf:port",
"//src/google/protobuf:protobuf_lite", "//src/google/protobuf:protobuf_lite",
"//src/google/protobuf/json",
"//src/google/protobuf/stubs", "//src/google/protobuf/stubs",
"//src/google/protobuf/util:json_util", "//src/google/protobuf/util:json_util",
"//src/google/protobuf/util:type_resolver", "//src/google/protobuf/util:type_resolver",
@ -304,6 +306,11 @@ py_binary(
], ],
) )
py_binary(
name = "update_failure_list",
srcs = ["update_failure_list.py"],
)
inline_sh_binary( inline_sh_binary(
name = "conformance_php", name = "conformance_php",
testonly = 1, testonly = 1,

@ -14,6 +14,7 @@
#include <cstring> #include <cstring>
#include <memory> #include <memory>
#include <string> #include <string>
#include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -25,6 +26,8 @@
#include "absl/strings/str_format.h" #include "absl/strings/str_format.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/strings/substitute.h" #include "absl/strings/substitute.h"
#include "json/reader.h"
#include "json/value.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "conformance_test.h" #include "conformance_test.h"
#include "conformance/test_protos/test_messages_edition2023.pb.h" #include "conformance/test_protos/test_messages_edition2023.pb.h"
@ -43,6 +46,7 @@
using conformance::ConformanceRequest; using conformance::ConformanceRequest;
using conformance::ConformanceResponse; using conformance::ConformanceResponse;
using conformance::TestStatus;
using conformance::WireFormat; using conformance::WireFormat;
using google::protobuf::Descriptor; using google::protobuf::Descriptor;
using google::protobuf::FieldDescriptor; using google::protobuf::FieldDescriptor;
@ -302,19 +306,22 @@ bool BinaryAndJsonConformanceSuite::ParseResponse(
const std::string& test_name = setting.GetTestName(); const std::string& test_name = setting.GetTestName();
ConformanceLevel level = setting.GetLevel(); ConformanceLevel level = setting.GetLevel();
TestStatus test;
test.set_name(test_name);
switch (response.result_case()) { switch (response.result_case()) {
case ConformanceResponse::kProtobufPayload: { case ConformanceResponse::kProtobufPayload: {
if (requested_output != conformance::PROTOBUF) { if (requested_output != conformance::PROTOBUF) {
ReportFailure(test_name, level, request, response, test.set_failure_message(absl::StrCat(
absl::StrCat("Test was asked for ", "Test was asked for ", WireFormatToString(requested_output),
WireFormatToString(requested_output),
" output but provided PROTOBUF instead.")); " output but provided PROTOBUF instead."));
ReportFailure(test, level, request, response);
return false; return false;
} }
if (!test_message->ParseFromString(response.protobuf_payload())) { if (!test_message->ParseFromString(response.protobuf_payload())) {
ReportFailure(test_name, level, request, response, test.set_failure_message(
"Protobuf output we received from test was unparseable."); "Protobuf output we received from test was unparseable.");
ReportFailure(test, level, request, response);
return false; return false;
} }
@ -323,16 +330,17 @@ bool BinaryAndJsonConformanceSuite::ParseResponse(
case ConformanceResponse::kJsonPayload: { case ConformanceResponse::kJsonPayload: {
if (requested_output != conformance::JSON) { if (requested_output != conformance::JSON) {
ReportFailure(test_name, level, request, response, test.set_failure_message(absl::StrCat(
absl::StrCat("Test was asked for ", "Test was asked for ", WireFormatToString(requested_output),
WireFormatToString(requested_output),
" output but provided JSON instead.")); " output but provided JSON instead."));
ReportFailure(test, level, request, response);
return false; return false;
} }
if (!ParseJsonResponse(response, test_message)) { if (!ParseJsonResponse(response, test_message)) {
ReportFailure(test_name, level, request, response, test.set_failure_message(
"JSON output we received from test was unparseable."); "JSON output we received from test was unparseable.");
ReportFailure(test, level, request, response);
return false; return false;
} }
@ -437,14 +445,19 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
absl::StrCat(setting.ConformanceLevelToString(level), ".", absl::StrCat(setting.ConformanceLevelToString(level), ".",
setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name); setting.GetSyntaxIdentifier(), ".ProtobufInput.", test_name);
suite_.RunTest(effective_test_name, request, &response); if (!suite_.RunTest(effective_test_name, request, &response)) {
return;
}
TestStatus test;
test.set_name(effective_test_name);
if (response.result_case() == ConformanceResponse::kParseError) { if (response.result_case() == ConformanceResponse::kParseError) {
suite_.ReportSuccess(effective_test_name); suite_.ReportSuccess(test);
} else if (response.result_case() == ConformanceResponse::kSkipped) { } else if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(effective_test_name, request, response); suite_.ReportSkip(test, request, response);
} else { } else {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message("Should have failed to parse, but didn't.");
"Should have failed to parse, but didn't."); suite_.ReportFailure(test, level, request, response);
} }
} }
@ -631,34 +644,38 @@ void BinaryAndJsonConformanceSuiteImpl<
setting.ConformanceLevelToString(level), ".", setting.ConformanceLevelToString(level), ".",
setting.GetSyntaxIdentifier(), ".JsonInput.", test_name, ".Validator"); setting.GetSyntaxIdentifier(), ".JsonInput.", test_name, ".Validator");
suite_.RunTest(effective_test_name, request, &response); if (!suite_.RunTest(effective_test_name, request, &response)) {
return;
}
TestStatus test;
test.set_name(effective_test_name);
if (response.result_case() == ConformanceResponse::kSkipped) { if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(effective_test_name, request, response); suite_.ReportSkip(test, request, response);
return; return;
} }
if (response.result_case() != ConformanceResponse::kJsonPayload) { if (response.result_case() != ConformanceResponse::kJsonPayload) {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message(absl::StrCat("Expected JSON payload but got type ",
absl::StrCat("Expected JSON payload but got type ",
response.result_case())); response.result_case()));
suite_.ReportFailure(test, level, request, response);
return; return;
} }
Json::Reader reader; Json::Reader reader;
Json::Value value; Json::Value value;
if (!reader.parse(response.json_payload(), value)) { if (!reader.parse(response.json_payload(), value)) {
suite_.ReportFailure( test.set_failure_message(
effective_test_name, level, request, response,
absl::StrCat("JSON payload cannot be parsed as valid JSON: ", absl::StrCat("JSON payload cannot be parsed as valid JSON: ",
reader.getFormattedErrorMessages())); reader.getFormattedErrorMessages()));
suite_.ReportFailure(test, level, request, response);
return; return;
} }
if (!validator(value)) { if (!validator(value)) {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message("JSON payload validation failed.");
"JSON payload validation failed."); suite_.ReportFailure(test, level, request, response);
return; return;
} }
suite_.ReportSuccess(effective_test_name); suite_.ReportSuccess(test);
} }
template <typename MessageType> template <typename MessageType>
@ -677,14 +694,19 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::ExpectParseFailureForJson(
absl::StrCat(setting.ConformanceLevelToString(level), ".", absl::StrCat(setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".JsonInput.", test_name); SyntaxIdentifier(), ".JsonInput.", test_name);
suite_.RunTest(effective_test_name, request, &response); if (!suite_.RunTest(effective_test_name, request, &response)) {
return;
}
TestStatus test;
test.set_name(effective_test_name);
if (response.result_case() == ConformanceResponse::kParseError) { if (response.result_case() == ConformanceResponse::kParseError) {
suite_.ReportSuccess(effective_test_name); suite_.ReportSuccess(test);
} else if (response.result_case() == ConformanceResponse::kSkipped) { } else if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(effective_test_name, request, response); suite_.ReportSkip(test, request, response);
} else { } else {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message("Should have failed to parse, but didn't.");
"Should have failed to parse, but didn't."); suite_.ReportFailure(test, level, request, response);
} }
} }
@ -707,14 +729,19 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
absl::StrCat(setting.ConformanceLevelToString(level), ".", absl::StrCat(setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".", test_name, ".JsonOutput"); SyntaxIdentifier(), ".", test_name, ".JsonOutput");
suite_.RunTest(effective_test_name, request, &response); if (!suite_.RunTest(effective_test_name, request, &response)) {
return;
}
TestStatus test;
test.set_name(effective_test_name);
if (response.result_case() == ConformanceResponse::kSerializeError) { if (response.result_case() == ConformanceResponse::kSerializeError) {
suite_.ReportSuccess(effective_test_name); suite_.ReportSuccess(test);
} else if (response.result_case() == ConformanceResponse::kSkipped) { } else if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(effective_test_name, request, response); suite_.ReportSkip(test, request, response);
} else { } else {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message("Should have failed to serialize, but didn't.");
"Should have failed to serialize, but didn't."); suite_.ReportFailure(test, level, request, response);
} }
} }
@ -1207,7 +1234,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestValidDataForOneofType(
{ {
// Tests oneof with default value. // Tests oneof with default value.
const std::string proto = default_value; const std::string& proto = default_value;
MessageType test_message; MessageType test_message;
test_message.MergeFromString(proto); test_message.MergeFromString(proto);
std::string text; std::string text;
@ -1223,7 +1250,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestValidDataForOneofType(
{ {
// Tests oneof with non-default value. // Tests oneof with non-default value.
const std::string proto = non_default_value; const std::string& proto = non_default_value;
MessageType test_message; MessageType test_message;
test_message.MergeFromString(proto); test_message.MergeFromString(proto);
std::string text; std::string text;
@ -1240,7 +1267,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestValidDataForOneofType(
{ {
// Tests oneof with multiple values of the same field. // Tests oneof with multiple values of the same field.
const std::string proto = absl::StrCat(default_value, non_default_value); const std::string proto = absl::StrCat(default_value, non_default_value);
const std::string expected_proto = non_default_value; const std::string& expected_proto = non_default_value;
MessageType test_message; MessageType test_message;
test_message.MergeFromString(expected_proto); test_message.MergeFromString(expected_proto);
std::string text; std::string text;
@ -1266,7 +1293,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestValidDataForOneofType(
GetDefaultValue(other_type)); GetDefaultValue(other_type));
const std::string proto = absl::StrCat(other_value, non_default_value); const std::string proto = absl::StrCat(other_value, non_default_value);
const std::string expected_proto = non_default_value; const std::string& expected_proto = non_default_value;
MessageType test_message; MessageType test_message;
test_message.MergeFromString(expected_proto); test_message.MergeFromString(expected_proto);
std::string text; std::string text;
@ -1420,12 +1447,18 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestUnknownOrdering() {
conformance::BINARY_TEST, prototype, "UnknownOrdering", serialized); conformance::BINARY_TEST, prototype, "UnknownOrdering", serialized);
const ConformanceRequest& request = setting.GetRequest(); const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response; ConformanceResponse response;
suite_.RunTest(setting.GetTestName(), request, &response); if (!suite_.RunTest(setting.GetTestName(), request, &response)) {
return;
}
MessageType response_message; MessageType response_message;
TestStatus test;
test.set_name(setting.GetTestName());
if (response.result_case() == ConformanceResponse::kSkipped) { if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(setting.GetTestName(), request, response); suite_.ReportSkip(test, request, response);
return; return;
} }
suite_.ParseResponse(response, setting, &response_message); suite_.ParseResponse(response, setting, &response_message);
const UnknownFieldSet& ufs = response_message.unknown_fields(); const UnknownFieldSet& ufs = response_message.unknown_fields();
@ -1441,10 +1474,10 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::TestUnknownOrdering() {
ufs.field(1).varint() != 123 || ufs.field(1).varint() != 123 ||
ufs.field(2).length_delimited() != "def" || ufs.field(2).length_delimited() != "def" ||
ufs.field(3).varint() != 456) { ufs.field(3).varint() != 456) {
suite_.ReportFailure(setting.GetTestName(), setting.GetLevel(), request, test.set_failure_message("Unknown field mismatch");
response, "Unknown field mismatch"); suite_.ReportFailure(test, setting.GetLevel(), request, response);
} else { } else {
suite_.ReportSuccess(setting.GetTestName()); suite_.ReportSuccess(test);
} }
} }

@ -57,11 +57,20 @@ enum TestCategory {
TEXT_FORMAT_TEST = 5; TEXT_FORMAT_TEST = 5;
} }
// Meant to encapsulate all types of tests: successes, skips, failures, etc.
// Therefore, this may or may not have a failure message. Failure messages
// may be truncated for our failure lists.
message TestStatus {
string name = 1;
string failure_message = 2;
}
// The conformance runner will request a list of failures as the first request. // The conformance runner will request a list of failures as the first request.
// This will be known by message_type == "conformance.FailureSet", a conformance // This will be known by message_type == "conformance.FailureSet", a conformance
// test should return a serialized FailureSet in protobuf_payload. // test should return a serialized FailureSet in protobuf_payload.
message FailureSet { message FailureSet {
repeated string failure = 1; repeated TestStatus test = 2;
reserved 1;
} }
// Represents a single test case's input. The testee should: // Represents a single test case's input. The testee should:

@ -7,15 +7,15 @@
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <memory> #include <memory>
#include <string> #include <string>
#include "google/protobuf/util/json_util.h"
#include "google/protobuf/util/type_resolver_util.h"
#include "absl/log/absl_check.h" #include "absl/log/absl_check.h"
#include "absl/log/absl_log.h" #include "absl/log/absl_log.h"
#include "absl/status/status.h" #include "absl/status/status.h"
@ -27,12 +27,15 @@
#include "editions/golden/test_messages_proto2_editions.pb.h" #include "editions/golden/test_messages_proto2_editions.pb.h"
#include "editions/golden/test_messages_proto3_editions.pb.h" #include "editions/golden/test_messages_proto3_editions.pb.h"
#include "google/protobuf/endian.h" #include "google/protobuf/endian.h"
#include "google/protobuf/json/json.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/test_messages_proto2.pb.h" #include "google/protobuf/test_messages_proto2.pb.h"
#include "google/protobuf/test_messages_proto3.pb.h" #include "google/protobuf/test_messages_proto3.pb.h"
#include "google/protobuf/test_messages_proto3.pb.h" #include "google/protobuf/test_messages_proto3.pb.h"
#include "google/protobuf/text_format.h" #include "google/protobuf/text_format.h"
#include "google/protobuf/util/json_util.h"
#include "google/protobuf/util/type_resolver.h" #include "google/protobuf/util/type_resolver.h"
#include "google/protobuf/util/type_resolver_util.h"
#include "google/protobuf/stubs/status_macros.h" #include "google/protobuf/stubs/status_macros.h"
// Must be included last. // Must be included last.
@ -241,8 +244,9 @@ absl::StatusOr<bool> Harness::ServeConformanceRequest() {
serialized_output.size())); serialized_output.size()));
if (verbose_) { if (verbose_) {
ABSL_LOG(INFO) << "conformance-cpp: request=" << request.ShortDebugString() ABSL_LOG(INFO) << "conformance-cpp: request="
<< ", response=" << response->ShortDebugString(); << google::protobuf::ShortFormat(request)
<< ", response=" << google::protobuf::ShortFormat(*response);
} }
return false; return false;
} }

@ -98,36 +98,38 @@ def do_test(request):
"Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64", "Required.Proto2.ProtobufInput.PrematureEofInPackedField.UINT64",
] ]
for x in failures: for x in failures:
failure_set.failure.append(x) failure_set.test.append(conformance_pb2.TestStatus(name=x))
response.protobuf_payload = failure_set.SerializeToString() response.protobuf_payload = failure_set.SerializeToString()
return response return response
isJson = (request.WhichOneof('payload') == 'json_payload') isJson = request.WhichOneof("payload") == "json_payload"
test_message = _create_test_message(request.message_type) test_message = _create_test_message(request.message_type)
if (not isJson) and (test_message is None): if (not isJson) and (test_message is None):
raise ProtocolError("Protobuf request doesn't have specific payload type") raise ProtocolError("Protobuf request doesn't have specific payload type")
try: try:
if request.WhichOneof('payload') == 'protobuf_payload': if request.WhichOneof("payload") == "protobuf_payload":
try: try:
test_message.ParseFromString(request.protobuf_payload) test_message.ParseFromString(request.protobuf_payload)
except message.DecodeError as e: except message.DecodeError as e:
response.parse_error = str(e) response.parse_error = str(e)
return response return response
elif request.WhichOneof('payload') == 'json_payload': elif request.WhichOneof("payload") == "json_payload":
try: try:
ignore_unknown_fields = \ ignore_unknown_fields = (
request.test_category == \ request.test_category
conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST == conformance_pb2.JSON_IGNORE_UNKNOWN_PARSING_TEST
json_format.Parse(request.json_payload, test_message, )
ignore_unknown_fields) json_format.Parse(
request.json_payload, test_message, ignore_unknown_fields
)
except Exception as e: except Exception as e:
response.parse_error = str(e) response.parse_error = str(e)
return response return response
elif request.WhichOneof('payload') == 'text_payload': elif request.WhichOneof("payload") == "text_payload":
try: try:
text_format.Parse(request.text_payload, test_message) text_format.Parse(request.text_payload, test_message)
except Exception as e: except Exception as e:
@ -152,7 +154,8 @@ def do_test(request):
elif request.requested_output_format == conformance_pb2.TEXT_FORMAT: elif request.requested_output_format == conformance_pb2.TEXT_FORMAT:
response.text_payload = text_format.MessageToString( response.text_payload = text_format.MessageToString(
test_message, print_unknown_fields=request.print_unknown_fields) test_message, print_unknown_fields=request.print_unknown_fields
)
except Exception as e: except Exception as e:
response.runtime_error = str(e) response.runtime_error = str(e)
@ -183,17 +186,24 @@ def do_test_io():
sys.stdout.buffer.flush() sys.stdout.buffer.flush()
if verbose: if verbose:
sys.stderr.write("conformance_python: request=%s, response=%s\n" % ( sys.stderr.write(
"conformance_python: request=%s, response=%s\n"
% (
request.ShortDebugString().c_str(), request.ShortDebugString().c_str(),
response.ShortDebugString().c_str())) response.ShortDebugString().c_str(),
)
)
global test_count global test_count
test_count += 1 test_count += 1
return True return True
while True: while True:
if not do_test_io(): if not do_test_io():
sys.stderr.write("conformance_python: received EOF from test runner " + sys.stderr.write(
"after %s tests, exiting\n" % (test_count)) "conformance_python: received EOF from test runner "
+ "after %s tests, exiting\n" % (test_count,)
)
sys.exit(0) sys.exit(0)

@ -7,12 +7,14 @@
use conformance_rust_proto::{ConformanceRequest, ConformanceResponse, WireFormat}; use conformance_rust_proto::{ConformanceRequest, ConformanceResponse, WireFormat};
#[cfg(cpp_kernel)] #[cfg(cpp_kernel)]
use protobuf_cpp as kernel; use protobuf_cpp as protobuf;
#[cfg(upb_kernel)] #[cfg(upb_kernel)]
use protobuf_upb as kernel; use protobuf_upb as protobuf;
use kernel::Optional::{Set, Unset}; use protobuf::prelude::*;
use protobuf::Optional::{Set, Unset};
use protobuf::ParseError;
use std::io::{self, ErrorKind, Read, Write}; use std::io::{self, ErrorKind, Read, Write};
use test_messages_edition2023_rust_proto::TestAllTypesEdition2023; use test_messages_edition2023_rust_proto::TestAllTypesEdition2023;
@ -73,52 +75,39 @@ fn do_test(req: &ConformanceRequest) -> ConformanceResponse {
Set(bytes) => bytes, Set(bytes) => bytes,
}; };
fn roundtrip<T: Message>(bytes: &[u8]) -> Result<Vec<u8>, ParseError> {
T::parse(bytes).map(|msg| msg.serialize().unwrap())
}
let serialized = match message_type.as_bytes() { let serialized = match message_type.as_bytes() {
b"protobuf_test_messages.proto2.TestAllTypesProto2" => { b"protobuf_test_messages.proto2.TestAllTypesProto2" => {
if let Ok(msg) = TestAllTypesProto2::parse(bytes) { roundtrip::<TestAllTypesProto2>(bytes)
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
} }
b"protobuf_test_messages.proto3.TestAllTypesProto3" => { b"protobuf_test_messages.proto3.TestAllTypesProto3" => {
if let Ok(msg) = TestAllTypesProto3::parse(bytes) { roundtrip::<TestAllTypesProto3>(bytes)
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
} }
b"protobuf_test_messages.editions.TestAllTypesEdition2023" => { b"protobuf_test_messages.editions.TestAllTypesEdition2023" => {
if let Ok(msg) = TestAllTypesEdition2023::parse(bytes) { roundtrip::<TestAllTypesEdition2023>(bytes)
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
} }
b"protobuf_test_messages.editions.proto2.TestAllTypesProto2" => { b"protobuf_test_messages.editions.proto2.TestAllTypesProto2" => {
if let Ok(msg) = EditionsTestAllTypesProto2::parse(bytes) { roundtrip::<EditionsTestAllTypesProto2>(bytes)
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
} }
b"protobuf_test_messages.editions.proto3.TestAllTypesProto3" => { b"protobuf_test_messages.editions.proto3.TestAllTypesProto3" => {
if let Ok(msg) = EditionsTestAllTypesProto3::parse(bytes) { roundtrip::<EditionsTestAllTypesProto3>(bytes)
msg.serialize().unwrap()
} else {
resp.set_parse_error("failed to parse bytes");
return resp;
}
} }
_ => panic!("unexpected msg type {message_type}"), _ => panic!("unexpected msg type {message_type}"),
}; };
match serialized {
Ok(serialized) => {
resp.set_protobuf_payload(serialized); resp.set_protobuf_payload(serialized);
return resp; }
Err(_) => {
resp.set_parse_error("failed to parse bytes");
}
}
resp
} }
fn main() { fn main() {

@ -9,14 +9,19 @@
#include <stdarg.h> #include <stdarg.h>
#include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdio>
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility>
#include "google/protobuf/util/field_comparator.h" #include "google/protobuf/util/field_comparator.h"
#include "google/protobuf/util/message_differencer.h" #include "google/protobuf/util/message_differencer.h"
#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/absl_check.h" #include "absl/log/absl_check.h"
#include "absl/log/absl_log.h" #include "absl/log/absl_log.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
@ -25,11 +30,13 @@
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "google/protobuf/descriptor_legacy.h" #include "google/protobuf/descriptor_legacy.h"
#include "google/protobuf/endian.h"
#include "google/protobuf/message.h" #include "google/protobuf/message.h"
#include "google/protobuf/text_format.h" #include "google/protobuf/text_format.h"
using conformance::ConformanceRequest; using conformance::ConformanceRequest;
using conformance::ConformanceResponse; using conformance::ConformanceResponse;
using conformance::TestStatus;
using conformance::WireFormat; using conformance::WireFormat;
using google::protobuf::util::DefaultFieldComparator; using google::protobuf::util::DefaultFieldComparator;
using google::protobuf::util::MessageDifferencer; using google::protobuf::util::MessageDifferencer;
@ -37,6 +44,15 @@ using std::string;
namespace { namespace {
static void ReplaceAll(std::string& input, std::string replace_word,
std::string replace_by) {
size_t pos = input.find(replace_word);
while (pos != std::string::npos) {
input.replace(pos, replace_word.length(), replace_by);
pos = input.find(replace_word, pos + replace_by.length());
}
}
static std::string ToOctString(const std::string& binary_string) { static std::string ToOctString(const std::string& binary_string) {
std::string oct_string; std::string oct_string;
for (size_t i = 0; i < binary_string.size(); i++) { for (size_t i = 0; i < binary_string.size(); i++) {
@ -52,16 +68,83 @@ static std::string ToOctString(const std::string& binary_string) {
return oct_string; return oct_string;
} }
template <typename SetT> // Returns full filename path of written .txt file if successful
bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file, static std::string ProduceOctalSerialized(const std::string& request,
absl::string_view msg, absl::string_view output_dir, uint32_t len) {
std::string* output) { char* len_split_bytes = static_cast<char*>(static_cast<void*>(&len));
std::string out;
std::string hex_repr;
for (int i = 0; i < 4; i++) {
auto conversion = (unsigned int)static_cast<uint8_t>(len_split_bytes[i]);
std::string hex = absl::StrFormat("\\x%x", conversion);
absl::StrAppend(&hex_repr, hex);
}
absl::StrAppend(&out, hex_repr);
absl::StrAppend(&out, ToOctString(request));
return out;
}
static std::string WriteToFile(const std::string& octal_serialized,
const std::string& output_dir,
const std::string& test_name) {
std::string test_name_txt = test_name;
ReplaceAll(test_name_txt, ".", "_");
absl::StrAppend(&test_name_txt, ".txt");
std::string full_filename;
if (!output_dir.empty()) {
full_filename = output_dir;
if (*output_dir.rbegin() != '/') {
full_filename.push_back('/');
}
absl::StrAppend(&full_filename, test_name_txt);
}
std::ofstream os{std::string(full_filename)};
if (os) {
os << octal_serialized;
return full_filename;
} else {
ABSL_LOG(INFO) << "Failed to open file for debugging: " << full_filename
<< "\n";
return "";
}
}
// Removes all newlines.
static void Normalize(std::string& input) {
input.erase(std::remove(input.begin(), input.end(), '\n'), input.end());
}
// Sets up a failure message properly for our failure lists.
static TestStatus FormatFailureMessage(TestStatus& input) {
// Make copy just this once, as we need to modify it for our failure lists.
std::string formatted_failure_message = input.failure_message();
// Remove newlines
Normalize(formatted_failure_message);
// Truncate failure message if needed
if (formatted_failure_message.length() > 128) {
formatted_failure_message = formatted_failure_message.substr(0, 128);
}
TestStatus properly_formatted;
properly_formatted.set_name(input.name());
properly_formatted.set_failure_message(formatted_failure_message);
return properly_formatted;
}
bool CheckSetEmpty(const absl::btree_map<std::string, TestStatus>& set_to_check,
absl::string_view write_to_file, absl::string_view msg,
absl::string_view output_dir, std::string* output) {
if (set_to_check.empty()) return true; if (set_to_check.empty()) return true;
absl::StrAppendFormat(output, "\n"); absl::StrAppendFormat(output, "\n");
absl::StrAppendFormat(output, "%s\n\n", msg); absl::StrAppendFormat(output, "%s\n\n", msg);
for (absl::string_view v : set_to_check) { for (const auto& pair : set_to_check) {
absl::StrAppendFormat(output, " %s\n", v); absl::StrAppendFormat(output, " %s # %s\n", pair.first,
pair.second.failure_message());
} }
absl::StrAppendFormat(output, "\n"); absl::StrAppendFormat(output, "\n");
@ -70,19 +153,18 @@ bool CheckSetEmpty(const SetT& set_to_check, absl::string_view write_to_file,
absl::string_view filename = write_to_file; absl::string_view filename = write_to_file;
if (!output_dir.empty()) { if (!output_dir.empty()) {
full_filename = std::string(output_dir); full_filename = std::string(output_dir);
if (*output_dir.rbegin() != '/') {
full_filename.push_back('/');
}
absl::StrAppend(&full_filename, write_to_file); absl::StrAppend(&full_filename, write_to_file);
filename = full_filename; filename = full_filename;
} }
std::ofstream os{std::string(filename)}; std::ofstream os{std::string(filename)};
if (os) { if (os) {
for (absl::string_view v : set_to_check) { for (const auto& pair : set_to_check) {
os << v << "\n"; os << pair.first << " # " << pair.second.failure_message() << "\n";
} }
} else { } else {
absl::StrAppendFormat(output, "Failed to open file: %s\n", filename); absl::StrAppendFormat(output,
"Failed to open file: %s\n",
filename);
} }
} }
@ -265,47 +347,72 @@ ConformanceResponse ConformanceTestSuite::TruncateResponse(
return debug_response; return debug_response;
} }
void ConformanceTestSuite::ReportSuccess(const std::string& test_name) { void ConformanceTestSuite::ReportSuccess(const TestStatus& test) {
if (expected_to_fail_.erase(test_name) != 0) { if (expected_to_fail_.erase(test.name()) != 0) {
absl::StrAppendFormat( absl::StrAppendFormat(
&output_, &output_,
"ERROR: test %s is in the failure list, but test succeeded. " "ERROR: test %s is in the failure list, but test succeeded. "
"Remove it from the failure list.\n", "Remove it from the failure list.\n",
test_name); test.name());
unexpected_succeeding_tests_.insert(test_name); unexpected_succeeding_tests_[test.name()] = test;
} }
successes_++; successes_++;
} }
void ConformanceTestSuite::ReportFailure(const std::string& test_name, void ConformanceTestSuite::ReportFailure(TestStatus& test,
ConformanceLevel level, ConformanceLevel level,
const ConformanceRequest& request, const ConformanceRequest& request,
const ConformanceResponse& response, const ConformanceResponse& response) {
absl::string_view message) { if (expected_to_fail_.contains(test.name())) {
if (expected_to_fail_.erase(test_name) == 1) { // Make copy just this once, as we need to modify them for comparison.
// Failure message from the failure list.
string expected_failure_message =
expected_to_fail_[test.name()].failure_message();
// Actual failure message from the test run.
std::string actual_failure_message = test.failure_message();
Normalize(actual_failure_message);
if (actual_failure_message.rfind(expected_failure_message, 0) == 0) {
// Our failure messages match.
expected_failures_++; expected_failures_++;
} else {
// We want to add the test to the failure list with its correct failure
// message.
unexpected_failure_messages_[test.name()] = FormatFailureMessage(test);
// We want to remove the test from the failure list. That means passing
// to it the same failure message that was in the list.
TestStatus incorrect_failure_message;
incorrect_failure_message.set_name(test.name());
incorrect_failure_message.set_failure_message(
expected_to_fail_[test.name()].failure_message());
expected_failure_messages_[test.name()] = incorrect_failure_message;
}
expected_to_fail_.erase(test.name());
if (!verbose_) return; if (!verbose_) return;
} else if (level == RECOMMENDED && !enforce_recommended_) { } else if (level == RECOMMENDED && !enforce_recommended_) {
absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test_name); absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test.name());
} else { } else {
absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test_name); absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test.name());
unexpected_failing_tests_.insert(test_name);
unexpected_failing_tests_[test.name()] = FormatFailureMessage(test);
} }
absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", message, absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n",
test.failure_message(),
TruncateRequest(request).ShortDebugString(), TruncateRequest(request).ShortDebugString(),
TruncateResponse(response).ShortDebugString()); TruncateResponse(response).ShortDebugString());
} }
void ConformanceTestSuite::ReportSkip(const std::string& test_name, void ConformanceTestSuite::ReportSkip(const TestStatus& test,
const ConformanceRequest& request, const ConformanceRequest& request,
const ConformanceResponse& response) { const ConformanceResponse& response) {
if (verbose_) { if (verbose_) {
absl::StrAppendFormat( absl::StrAppendFormat(
&output_, "SKIPPED, test=%s request=%s, response=%s\n", test_name, &output_, "SKIPPED, test=%s request=%s, response=%s\n", test.name(),
request.ShortDebugString(), response.ShortDebugString()); request.ShortDebugString(), response.ShortDebugString());
} }
skipped_.insert(test_name); skipped_[test.name()] = test;
} }
void ConformanceTestSuite::RunValidInputTest( void ConformanceTestSuite::RunValidInputTest(
@ -326,7 +433,10 @@ void ConformanceTestSuite::RunValidBinaryInputTest(
const std::string& equivalent_wire_format, bool require_same_wire_format) { const std::string& equivalent_wire_format, bool require_same_wire_format) {
const ConformanceRequest& request = setting.GetRequest(); const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response; ConformanceResponse response;
RunTest(setting.GetTestName(), request, &response); if (!RunTest(setting.GetTestName(), request, &response)) {
return;
}
VerifyResponse(setting, equivalent_wire_format, response, true, VerifyResponse(setting, equivalent_wire_format, response, true,
require_same_wire_format); require_same_wire_format);
} }
@ -345,22 +455,26 @@ void ConformanceTestSuite::VerifyResponse(
ABSL_CHECK(reference_message->ParseFromString(equivalent_wire_format)) ABSL_CHECK(reference_message->ParseFromString(equivalent_wire_format))
<< "Failed to parse wire data for test case: " << test_name; << "Failed to parse wire data for test case: " << test_name;
TestStatus test;
test.set_name(test_name);
switch (response.result_case()) { switch (response.result_case()) {
case ConformanceResponse::RESULT_NOT_SET: case ConformanceResponse::RESULT_NOT_SET:
ReportFailure(test_name, level, request, response, test.set_failure_message(
"Response didn't have any field in the Response."); "Response didn't have any field in the Response.");
ReportFailure(test, level, request, response);
return; return;
case ConformanceResponse::kParseError: case ConformanceResponse::kParseError:
case ConformanceResponse::kTimeoutError: case ConformanceResponse::kTimeoutError:
case ConformanceResponse::kRuntimeError: case ConformanceResponse::kRuntimeError:
case ConformanceResponse::kSerializeError: case ConformanceResponse::kSerializeError:
ReportFailure(test_name, level, request, response, test.set_failure_message("Failed to parse input or produce output.");
"Failed to parse input or produce output."); ReportFailure(test, level, request, response);
return; return;
case ConformanceResponse::kSkipped: case ConformanceResponse::kSkipped:
ReportSkip(test_name, request, response); ReportSkip(test, request, response);
return; return;
default: default:
@ -386,20 +500,18 @@ void ConformanceTestSuite::VerifyResponse(
} else { } else {
check = differencer.Compare(*reference_message, *test_message); check = differencer.Compare(*reference_message, *test_message);
} }
if (check) { if (check) {
if (need_report_success) { if (need_report_success) {
ReportSuccess(test_name); ReportSuccess(test);
} }
} else { } else {
ReportFailure( test.set_failure_message(absl::StrCat(
test_name, level, request, response, "Output was not equivalent to reference message: ", differences));
absl::StrCat("Output was not equivalent to reference message: ", ReportFailure(test, level, request, response);
differences));
} }
} }
void ConformanceTestSuite::RunTest(const std::string& test_name, bool ConformanceTestSuite::RunTest(const std::string& test_name,
const ConformanceRequest& request, const ConformanceRequest& request,
ConformanceResponse* response) { ConformanceResponse* response) {
if (test_names_.insert(test_name).second == false) { if (test_names_.insert(test_name).second == false) {
@ -410,7 +522,43 @@ void ConformanceTestSuite::RunTest(const std::string& test_name,
std::string serialized_response; std::string serialized_response;
request.SerializeToString(&serialized_request); request.SerializeToString(&serialized_request);
runner_->RunTest(test_name, serialized_request, &serialized_response); uint32_t len = internal::little_endian::FromHost(
static_cast<uint32_t>(serialized_request.size()));
if (!debug_) { // Not in debug mode. Continue.
} else if (debug_test_names_->erase(test_name) == 1) {
std::string octal = ProduceOctalSerialized(serialized_request, len);
std::string full_filename = WriteToFile(octal, output_dir_, test_name);
if (!full_filename.empty()) {
absl::StrAppendFormat(
&output_, "Produced octal serialized request file for test %s\n",
test_name);
absl::StrAppendFormat(
&output_,
" To pipe the "
"serialized request directly to "
"the "
"testee run from the root of your workspace:\n printf $("
"<\"%s\") | "
"./bazel-bin/google/protobuf/conformance/%s\n\n",
full_filename, testee_);
absl::StrAppendFormat(
&output_,
" To inspect the wire format of the serialized request run "
"(Disclaimer: This may not work properly on non-Linux platforms):\n "
" "
"contents=$(<\"%s\"); sub=$(cut -d \\\\ -f 6- <<< "
"$contents) ; printf \"\\\\${sub}\" | protoscope \n\n\n",
full_filename);
}
} else { // Test is not ran, as it was not asked to be debugged.
expected_to_fail_.erase(test_name);
return false;
}
response->set_protobuf_payload(serialized_request);
runner_->RunTest(test_name, len, serialized_request, &serialized_response);
if (!response->ParseFromString(serialized_response)) { if (!response->ParseFromString(serialized_response)) {
response->Clear(); response->Clear();
@ -423,6 +571,7 @@ void ConformanceTestSuite::RunTest(const std::string& test_name,
test_name, TruncateRequest(request).ShortDebugString(), test_name, TruncateRequest(request).ShortDebugString(),
TruncateResponse(*response).ShortDebugString()); TruncateResponse(*response).ShortDebugString());
} }
return true;
} }
std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) { std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) {
@ -443,8 +592,8 @@ std::string ConformanceTestSuite::WireFormatToString(WireFormat wire_format) {
return ""; return "";
} }
void ConformanceTestSuite::AddExpectedFailedTest(const std::string& test_name) { void ConformanceTestSuite::AddExpectedFailedTest(const TestStatus& failure) {
expected_to_fail_.insert(test_name); expected_to_fail_[failure.name()] = failure;
} }
bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner, bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
@ -459,46 +608,89 @@ bool ConformanceTestSuite::RunSuite(ConformanceTestRunner* runner,
unexpected_failing_tests_.clear(); unexpected_failing_tests_.clear();
unexpected_succeeding_tests_.clear(); unexpected_succeeding_tests_.clear();
output_ = "\nCONFORMANCE TEST BEGIN ====================================\n\n"; std::string mode = debug_ ? "DEBUG" : "TEST";
absl::StrAppendFormat(
&output_, "CONFORMANCE %s BEGIN ====================================\n\n",
mode);
failure_list_filename_ = filename; failure_list_filename_ = filename;
expected_to_fail_.clear(); expected_to_fail_.clear();
for (const std::string& failure : failure_list->failure()) { for (const TestStatus& failure : failure_list->test()) {
AddExpectedFailedTest(failure); AddExpectedFailedTest(failure);
} }
RunSuiteImpl(); RunSuiteImpl();
if (*output_dir_.rbegin() != '/') {
output_dir_.push_back('/');
}
bool ok = true; bool ok = true;
if (!CheckSetEmpty( if (!CheckSetEmpty(
expected_to_fail_, "nonexistent_tests.txt", expected_to_fail_, "nonexistent_tests.txt",
absl::StrCat("These tests were listed in the failure list, but they " absl::StrCat(
"These tests were listed in the failure list, but they "
"don't exist. Remove them from the failure list by " "don't exist. Remove them from the failure list by "
"running:\n" "running from the root of your workspace:\n"
" ./update_failure_list.py ", " bazel run "
failure_list_filename_, "//google/protobuf/conformance:update_failure_list -- ",
" --remove nonexistent_tests.txt"), failure_list_filename_, " --remove ", output_dir_,
"nonexistent_tests.txt"),
output_dir_, &output_)) {
ok = false;
}
if (!CheckSetEmpty(
expected_failure_messages_, "expected_failure_messages.txt",
absl::StrCat(
"These tests were listed in the failure list, but their failure "
"messages do not match. Remove them from the failure list "
"by running:\n"
" bazel run ",
"//google/protobuf/conformance:update_failure_list -- ",
failure_list_filename_, " --remove ", output_dir_,
"expected_failure_messages.txt"),
output_dir_, &output_)) { output_dir_, &output_)) {
ok = false; ok = false;
} }
if (!CheckSetEmpty(
unexpected_failure_messages_, "unexpected_failure_messages.txt",
absl::StrCat(
"These tests failed because their failure messages did "
"not match. If they can't be fixed right now, "
"you can add them to the failure list so the overall "
"suite can succeed. Add them to the failure list by "
"running from the root of your workspace:\n"
" bazel run "
"//google/protobuf/conformance:update_failure_list -- ",
failure_list_filename_, " --add ", output_dir_,
"unexpected_failure_messages.txt"),
output_dir_, &output_)) {
ok = false;
}
if (!CheckSetEmpty( if (!CheckSetEmpty(
unexpected_failing_tests_, "failing_tests.txt", unexpected_failing_tests_, "failing_tests.txt",
absl::StrCat("These tests failed. If they can't be fixed right now, " absl::StrCat(
"These tests failed. If they can't be fixed right now, "
"you can add them to the failure list so the overall " "you can add them to the failure list so the overall "
"suite can succeed. Add them to the failure list by " "suite can succeed. Add them to the failure list by "
"running:\n" "running from the root of your workspace:\n"
" ./update_failure_list.py ", " bazel run "
failure_list_filename_, " --add failing_tests.txt"), "//google/protobuf/conformance:update_failure_list -- ",
failure_list_filename_, " --add ", output_dir_,
"failing_tests.txt"),
output_dir_, &output_)) { output_dir_, &output_)) {
ok = false; ok = false;
} }
if (!CheckSetEmpty( if (!CheckSetEmpty(
unexpected_succeeding_tests_, "succeeding_tests.txt", unexpected_succeeding_tests_, "succeeding_tests.txt",
absl::StrCat("These tests succeeded, even though they were listed in " absl::StrCat(
"the failure list. Remove them from the failure list " "These tests succeeded, even though they were listed in "
"by running:\n" "the failure list. Remove them from the failure list by running "
" ./update_failure_list.py ", "from the root of your workspace:\n"
failure_list_filename_, " bazel run "
" --remove succeeding_tests.txt"), "//google/protobuf/conformance:update_failure_list -- ",
failure_list_filename_, " --remove ", output_dir_,
"succeeding_tests.txt"),
output_dir_, &output_)) { output_dir_, &output_)) {
ok = false; ok = false;
} }

@ -15,18 +15,17 @@
#define CONFORMANCE_CONFORMANCE_TEST_H #define CONFORMANCE_CONFORMANCE_TEST_H
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/util/type_resolver.h" #include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_set.h" #include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h" #include "conformance/conformance.pb.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/wire_format_lite.h"
namespace conformance { namespace conformance {
class ConformanceRequest; class ConformanceRequest;
@ -46,17 +45,18 @@ class ConformanceTestSuite;
class ConformanceTestRunner { class ConformanceTestRunner {
public: public:
virtual ~ConformanceTestRunner() {} virtual ~ConformanceTestRunner() = default;
// Call to run a single conformance test. // Call to run a single conformance test.
// //
// "len" is the byte length of a serialized conformance.ConformanceRequest.
// "input" is a serialized conformance.ConformanceRequest. // "input" is a serialized conformance.ConformanceRequest.
// "output" should be set to a serialized conformance.ConformanceResponse. // "output" should be set to a serialized conformance.ConformanceResponse.
// //
// If there is any error in running the test itself, set "runtime_error" in // If there is any error in running the test itself, set "runtime_error" in
// the response. // the response.
virtual void RunTest(const std::string& test_name, const std::string& input, virtual void RunTest(const std::string& test_name, uint32_t len,
std::string* output) = 0; const std::string& input, std::string* output) = 0;
}; };
// Test runner that spawns the process being tested and communicates with it // Test runner that spawns the process being tested and communicates with it
@ -78,10 +78,10 @@ class ForkPipeRunner : public ConformanceTestRunner {
explicit ForkPipeRunner(const std::string& executable) explicit ForkPipeRunner(const std::string& executable)
: child_pid_(-1), executable_(executable) {} : child_pid_(-1), executable_(executable) {}
virtual ~ForkPipeRunner() {} ~ForkPipeRunner() override = default;
void RunTest(const std::string& test_name, const std::string& request, void RunTest(const std::string& test_name, uint32_t len,
std::string* response); const std::string& request, std::string* response) override;
private: private:
void SpawnTestProgram(); void SpawnTestProgram();
@ -129,12 +129,15 @@ class ForkPipeRunner : public ConformanceTestRunner {
class ConformanceTestSuite { class ConformanceTestSuite {
public: public:
ConformanceTestSuite() ConformanceTestSuite()
: verbose_(false), : testee_(""),
verbose_(false),
performance_(false), performance_(false),
enforce_recommended_(false), enforce_recommended_(false),
maximum_edition_(Edition::EDITION_PROTO3), maximum_edition_(Edition::EDITION_PROTO3),
failure_list_flag_name_("--failure_list") {} failure_list_flag_name_("--failure_list"),
virtual ~ConformanceTestSuite() {} debug_test_names_(nullptr),
debug_(false) {}
virtual ~ConformanceTestSuite() = default;
void SetPerformance(bool performance) { performance_ = performance; } void SetPerformance(bool performance) { performance_ = performance; }
void SetVerbose(bool verbose) { verbose_ = verbose; } void SetVerbose(bool verbose) { verbose_ = verbose; }
@ -161,7 +164,18 @@ class ConformanceTestSuite {
} }
// Sets the path of the output directory. // Sets the path of the output directory.
void SetOutputDir(const char* output_dir) { output_dir_ = output_dir; } void SetOutputDir(const std::string& output_dir) { output_dir_ = output_dir; }
// Sets if we are running the test in debug mode.
void SetDebug(bool debug) { debug_ = debug; }
// Sets the testee name
void SetTestee(const std::string& testee) { testee_ = testee; }
// Sets the debug test names
void SetDebugTestNames(absl::flat_hash_set<std::string>& debug_test_names) {
debug_test_names_ = &debug_test_names;
}
// Run all the conformance tests against the given test runner. // Run all the conformance tests against the given test runner.
// Test output will be stored in "output". // Test output will be stored in "output".
@ -170,6 +184,9 @@ class ConformanceTestSuite {
// failure list. // failure list.
// The filename here is *only* used to create/format useful error messages for // The filename here is *only* used to create/format useful error messages for
// how to update the failure list. We do NOT read this file at all. // how to update the failure list. We do NOT read this file at all.
// "debug_test_names" holds the list of test names that the user requested to
// debug. If this is empty, we will run all the tests.
bool RunSuite(ConformanceTestRunner* runner, std::string* output, bool RunSuite(ConformanceTestRunner* runner, std::string* output,
const std::string& filename, const std::string& filename,
conformance::FailureSet* failure_list); conformance::FailureSet* failure_list);
@ -201,7 +218,7 @@ class ConformanceTestSuite {
const Message& prototype_message, const Message& prototype_message,
const std::string& test_name, const std::string& test_name,
const std::string& input); const std::string& input);
virtual ~ConformanceRequestSetting() {} virtual ~ConformanceRequestSetting() = default;
std::unique_ptr<Message> NewTestMessage() const; std::unique_ptr<Message> NewTestMessage() const;
@ -259,12 +276,11 @@ class ConformanceTestSuite {
conformance::ConformanceResponse TruncateResponse( conformance::ConformanceResponse TruncateResponse(
const conformance::ConformanceResponse& response); const conformance::ConformanceResponse& response);
void ReportSuccess(const std::string& test_name); void ReportSuccess(const conformance::TestStatus& test);
void ReportFailure(const std::string& test_name, ConformanceLevel level, void ReportFailure(conformance::TestStatus& test, ConformanceLevel level,
const conformance::ConformanceRequest& request, const conformance::ConformanceRequest& request,
const conformance::ConformanceResponse& response, const conformance::ConformanceResponse& response);
absl::string_view message); void ReportSkip(const conformance::TestStatus& test,
void ReportSkip(const std::string& test_name,
const conformance::ConformanceRequest& request, const conformance::ConformanceRequest& request,
const conformance::ConformanceResponse& response); const conformance::ConformanceResponse& response);
@ -274,15 +290,17 @@ class ConformanceTestSuite {
const std::string& equivalent_wire_format, const std::string& equivalent_wire_format,
bool require_same_wire_format = false); bool require_same_wire_format = false);
void RunTest(const std::string& test_name, // Returns true if our runner_ ran the test and false if it did not.
bool RunTest(const std::string& test_name,
const conformance::ConformanceRequest& request, const conformance::ConformanceRequest& request,
conformance::ConformanceResponse* response); conformance::ConformanceResponse* response);
void AddExpectedFailedTest(const std::string& test_name); void AddExpectedFailedTest(const conformance::TestStatus& failure);
virtual void RunSuiteImpl() = 0; virtual void RunSuiteImpl() = 0;
ConformanceTestRunner* runner_; ConformanceTestRunner* runner_;
std::string testee_;
int successes_; int successes_;
int expected_failures_; int expected_failures_;
bool verbose_; bool verbose_;
@ -293,23 +311,41 @@ class ConformanceTestSuite {
std::string output_dir_; std::string output_dir_;
std::string failure_list_flag_name_; std::string failure_list_flag_name_;
std::string failure_list_filename_; std::string failure_list_filename_;
absl::flat_hash_set<std::string>* debug_test_names_;
bool debug_;
// The set of test names that are expected to fail in this run, but haven't // The set of test names that are expected to fail in this run, but haven't
// failed yet. // failed yet.
absl::btree_set<std::string> expected_to_fail_; absl::btree_map<std::string, conformance::TestStatus> expected_to_fail_;
// The set of tests that failed because their failure message did not match
// the actual failure message. These are failure messages that may need to be
// removed from our failure lists.
absl::btree_map<std::string, conformance::TestStatus>
expected_failure_messages_;
// The set of test names that have been run. Used to ensure that there are no // The set of test names that have been run. Used to ensure that there are no
// duplicate names in the suite. // duplicate names in the suite.
absl::flat_hash_set<std::string> test_names_; absl::flat_hash_set<std::string> test_names_;
// The set of tests that failed, but weren't expected to. // The set of tests that failed, but weren't expected to: They weren't
absl::btree_set<std::string> unexpected_failing_tests_; // present in our failure lists.
absl::btree_map<std::string, conformance::TestStatus>
unexpected_failing_tests_;
// The set of tests that succeeded, but weren't expected to: They were present
// in our failure lists, but managed to succeed.
absl::btree_map<std::string, conformance::TestStatus>
unexpected_succeeding_tests_;
// The set of tests that succeeded, but weren't expected to. // The set of tests that failed because their failure message did not match
absl::btree_set<std::string> unexpected_succeeding_tests_; // the actual failure message. These are failure messages that may need to be
// added to our failure lists.
absl::btree_map<std::string, conformance::TestStatus>
unexpected_failure_messages_;
// The set of tests that the testee opted out of; // The set of tests that the testee opted out of;
absl::btree_set<std::string> skipped_; absl::btree_map<std::string, conformance::TestStatus> skipped_;
}; };
} // namespace protobuf } // namespace protobuf

@ -32,26 +32,32 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#include <algorithm> #include <algorithm>
#include <cctype>
#include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <fstream> #include <fstream>
#include <future> #include <future>
#include <string>
#include <vector> #include <vector>
#include "absl/container/flat_hash_set.h"
#include "absl/log/absl_log.h" #include "absl/log/absl_log.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h" #include "absl/strings/str_format.h"
#include "conformance/conformance.pb.h" #include "conformance/conformance.pb.h"
#include "conformance/conformance.pb.h"
#include "conformance_test.h" #include "conformance_test.h"
#include "google/protobuf/endian.h" #include "google/protobuf/endian.h"
using conformance::ConformanceResponse;
using google::protobuf::ConformanceTestSuite; using google::protobuf::ConformanceTestSuite;
using std::string; using std::string;
using std::vector; using std::vector;
@ -76,15 +82,34 @@ void ParseFailureList(const char *filename,
exit(1); exit(1);
} }
for (string line; getline(infile, line);) { for (string line; std::getline(infile, line);) {
// Remove whitespace.
line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end());
// Remove comments. // Remove comments.
line = line.substr(0, line.find("#")); string test_name = line.substr(0, line.find('#'));
test_name.erase(
std::remove_if(test_name.begin(), test_name.end(), ::isspace),
test_name.end());
if (!line.empty()) { if (test_name.empty()) { // Skip empty lines.
failure_list->add_failure(line); continue;
}
// If we remove whitespace from the beginning of a line, and what we have
// left at first is a '#', then we have a comment.
if (test_name[0] != '#') {
// Find our failure message if it exists. Will be set to an empty string
// if no message is found. Empty failure messages also pass our tests.
size_t check_message = line.find('#');
string message;
if (check_message != std::string::npos) {
message = line.substr(check_message + 1); // +1 to skip the delimiter
// If we had only whitespace after the delimiter, we will have an empty
// failure message and the test will still pass.
message = std::string(absl::StripAsciiWhitespace(message));
}
conformance::TestStatus *test = failure_list->add_test();
test->set_name(test_name);
test->set_failure_message(message);
} }
} }
} }
@ -100,7 +125,7 @@ void UsageError() {
fprintf(stderr, fprintf(stderr,
" should contain one test name per\n"); " should contain one test name per\n");
fprintf(stderr, fprintf(stderr,
" line. Use '#' for comments.\n"); " line. Use '#' for comments.\n\n");
fprintf(stderr, fprintf(stderr,
" --text_format_failure_list <filename> Use to specify list \n"); " --text_format_failure_list <filename> Use to specify list \n");
fprintf(stderr, fprintf(stderr,
@ -111,7 +136,7 @@ void UsageError() {
fprintf(stderr, fprintf(stderr,
" File should contain one test name \n"); " File should contain one test name \n");
fprintf(stderr, fprintf(stderr,
" per line. Use '#' for comments.\n"); " per line. Use '#' for comments.\n\n");
fprintf(stderr, fprintf(stderr,
" --enforce_recommended Enforce that recommended test\n"); " --enforce_recommended Enforce that recommended test\n");
@ -121,19 +146,30 @@ void UsageError() {
" this flag if you want to be\n"); " this flag if you want to be\n");
fprintf(stderr, fprintf(stderr,
" strictly conforming to protobuf\n"); " strictly conforming to protobuf\n");
fprintf(stderr, " spec.\n"); fprintf(stderr, " spec.\n\n");
fprintf(stderr, fprintf(stderr,
" --maximum_edition <edition> Only run conformance tests up\n"); " --maximum_edition <edition> Only run conformance tests up to\n");
fprintf(stderr, fprintf(stderr,
" to and including the specified\n"); " and including the specified\n");
fprintf(stderr, " edition.\n"); fprintf(stderr, " edition.\n\n");
fprintf(stderr, fprintf(stderr,
" --output_dir <dirname> Directory to write\n" " --output_dir <dirname> Directory to write\n"
" output files.\n"); " output files.\n\n");
fprintf(stderr,
" --debug <test_name1> <test_name2> ... <test_nameN> Debug the \n");
fprintf(stderr, " specified tests by running\n");
fprintf(stderr,
" them in isolation and producing\n");
fprintf(stderr,
" serialized request data for piping\n");
fprintf(stderr, " directly to the testee.\n\n");
fprintf(stderr, " --performance Boolean option\n");
fprintf(stderr, " for enabling run of\n");
fprintf(stderr, " performance tests.\n");
exit(1); exit(1);
} }
void ForkPipeRunner::RunTest(const std::string &test_name, void ForkPipeRunner::RunTest(const std::string &test_name, uint32_t len,
const std::string &request, const std::string &request,
std::string *response) { std::string *response) {
if (child_pid_ < 0) { if (child_pid_ < 0) {
@ -141,8 +177,6 @@ void ForkPipeRunner::RunTest(const std::string &test_name,
} }
current_test_name_ = test_name; current_test_name_ = test_name;
uint32_t len =
internal::little_endian::FromHost(static_cast<uint32_t>(request.size()));
CheckedWrite(write_fd_, &len, sizeof(uint32_t)); CheckedWrite(write_fd_, &len, sizeof(uint32_t));
CheckedWrite(write_fd_, request.c_str(), request.size()); CheckedWrite(write_fd_, request.c_str(), request.size());
@ -188,26 +222,25 @@ int ForkPipeRunner::Run(int argc, char *argv[],
fprintf(stderr, "No test suites found.\n"); fprintf(stderr, "No test suites found.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
bool all_ok = true;
for (ConformanceTestSuite *suite : suites) {
string program; string program;
string testee;
std::vector<string> program_args; std::vector<string> program_args;
string failure_list_filename;
conformance::FailureSet failure_list;
bool performance = false; bool performance = false;
bool debug = false;
absl::flat_hash_set<string> debug_test_names;
bool enforce_recommended = false;
Edition maximum_edition = EDITION_UNKNOWN;
std::string output_dir;
bool verbose = false;
for (int arg = 1; arg < argc; ++arg) { for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) { if (strcmp(argv[arg], "--performance") == 0) {
if (++arg == argc) UsageError();
failure_list_filename = argv[arg];
ParseFailureList(argv[arg], &failure_list);
} else if (strcmp(argv[arg], "--performance") == 0) {
performance = true; performance = true;
suite->SetPerformance(true);
} else if (strcmp(argv[arg], "--verbose") == 0) { } else if (strcmp(argv[arg], "--verbose") == 0) {
suite->SetVerbose(true); verbose = true;
} else if (strcmp(argv[arg], "--enforce_recommended") == 0) { } else if (strcmp(argv[arg], "--enforce_recommended") == 0) {
suite->SetEnforceRecommended(true); enforce_recommended = true;
} else if (strcmp(argv[arg], "--maximum_edition") == 0) { } else if (strcmp(argv[arg], "--maximum_edition") == 0) {
if (++arg == argc) UsageError(); if (++arg == argc) UsageError();
Edition edition = EDITION_UNKNOWN; Edition edition = EDITION_UNKNOWN;
@ -215,10 +248,23 @@ int ForkPipeRunner::Run(int argc, char *argv[],
fprintf(stderr, "Unknown edition: %s\n", argv[arg]); fprintf(stderr, "Unknown edition: %s\n", argv[arg]);
UsageError(); UsageError();
} }
suite->SetMaximumEdition(edition); maximum_edition = edition;
} else if (strcmp(argv[arg], "--output_dir") == 0) { } else if (strcmp(argv[arg], "--output_dir") == 0) {
if (++arg == argc) UsageError(); if (++arg == argc) UsageError();
suite->SetOutputDir(argv[arg]); output_dir = argv[arg];
} else if (strcmp(argv[arg], "--debug") == 0) {
if (++arg == argc) UsageError();
for (int debug_arg = arg; debug_arg < argc; ++debug_arg) {
// Stop when we either find another flag or we reach the last arg
// (program arg)
if (argv[debug_arg][0] == '-' || debug_arg == argc - 1) {
arg = debug_arg - 1;
break;
}
debug_test_names.insert(argv[debug_arg]);
}
} else if (argv[arg][0] == '-') { } else if (argv[arg][0] == '-') {
bool recognized_flag = false; bool recognized_flag = false;
for (ConformanceTestSuite *suite : suites) { for (ConformanceTestSuite *suite : suites) {
@ -240,6 +286,34 @@ int ForkPipeRunner::Run(int argc, char *argv[],
} }
} }
if (!debug_test_names.empty()) {
debug = true;
}
auto last_slash = program.find_last_of('/');
if (last_slash != string::npos) {
testee = program.substr(last_slash + 1);
}
bool all_ok = true;
for (ConformanceTestSuite *suite : suites) {
string failure_list_filename;
conformance::FailureSet failure_list;
for (int arg = 1; arg < argc; ++arg) {
if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) {
if (++arg == argc) UsageError();
failure_list_filename = argv[arg];
ParseFailureList(argv[arg], &failure_list);
}
}
suite->SetPerformance(performance);
suite->SetVerbose(verbose);
suite->SetEnforceRecommended(enforce_recommended);
suite->SetMaximumEdition(maximum_edition);
suite->SetOutputDir(output_dir);
suite->SetDebug(debug);
suite->SetDebugTestNames(debug_test_names);
suite->SetTestee(testee);
ForkPipeRunner runner(program, program_args, performance); ForkPipeRunner runner(program, program_args, performance);
std::string output; std::string output;
@ -248,6 +322,16 @@ int ForkPipeRunner::Run(int argc, char *argv[],
fwrite(output.c_str(), 1, output.size(), stderr); fwrite(output.c_str(), 1, output.size(), stderr);
} }
if (!debug_test_names.empty()) {
fprintf(stderr,
"These tests were requested to be debugged, but they do "
"not exist. Revise the test names:\n\n");
for (const string &test_name : debug_test_names) {
fprintf(stderr, " %s\n", test_name.c_str());
}
fprintf(stderr, "\n\n");
}
return all_ok ? EXIT_SUCCESS : EXIT_FAILURE; return all_ok ? EXIT_SUCCESS : EXIT_FAILURE;
} }

@ -7,105 +7,105 @@
# TODO: insert links to corresponding bugs tracking the issue. # TODO: insert links to corresponding bugs tracking the issue.
# Should we use GitHub issues or the Google-internal bug tracker? # Should we use GitHub issues or the Google-internal bug tracker?
Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key2]: FOO
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key]: FOO
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Editions_Proto2.JsonInput.MapFieldValueIsNull # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Editions_Proto2.JsonInput.RepeatedFieldMessageElementIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Editions_Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameDuplicate Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingComma # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameNotQuoted Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted Recommended.Editions_Proto2.JsonInput.StringFieldUppercaseEscapeLetter # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObject # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Proto3.JsonInput.MapFieldValueIsNull Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto3.JsonInput.MapFieldValueIsNull Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingComma Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key2]: FOO
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key]: FOO
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace Recommended.Editions_Proto3.JsonInput.MapFieldValueIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace Recommended.Editions_Proto3.JsonInput.RepeatedFieldMessageElementIsNull # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace Recommended.Editions_Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingComma # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter Recommended.Editions_Proto3.JsonInput.StringFieldUppercaseEscapeLetter # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldUppercaseEscapeLetter Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObject # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.TrailingCommaInAnObject Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObject Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpace # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto2.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto2.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1
Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto2.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key2]: FOO
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key]: FOO
Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate Recommended.Proto2.JsonInput.MapFieldValueIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 Recommended.Proto2.JsonInput.RepeatedFieldMessageElementIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 Recommended.Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted Recommended.Proto2.JsonInput.RepeatedFieldTrailingComma # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.MapFieldValueIsNull Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingComma Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace Recommended.Proto2.JsonInput.StringFieldUppercaseEscapeLetter # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace Recommended.Proto2.JsonInput.TrailingCommaInAnObject # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldUppercaseEscapeLetter Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObject Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Proto3.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameDuplicate Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1 # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing1 Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2 # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameDuplicateDifferentCasing2 Recommended.Proto3.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameNotQuoted Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapPart.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key2]: FOO
Recommended.Proto2.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput # Output was not equivalent to reference message: added: map_string_nested_enum[key]: FOO
Recommended.Proto2.JsonInput.MapFieldValueIsNull Recommended.Proto3.JsonInput.MapFieldValueIsNull # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldMessageElementIsNull Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldPrimitiveElementIsNull Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldTrailingComma Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithNewlines Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpace Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldUppercaseEscapeLetter Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.TrailingCommaInAnObject Recommended.Proto3.JsonInput.TrailingCommaInAnObject # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithNewlines Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpace Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace # Should have failed to parse, but didn't.

@ -4,149 +4,149 @@
# By listing them here we can keep tabs on which ones are failing and be sure # By listing them here we can keep tabs on which ones are failing and be sure
# that we don't introduce regressions in other tests. # that we don't introduce regressions in other tests.
Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalFalse # Should have failed to parse, but didn't.
Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalTrue # Should have failed to parse, but didn't.
Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseFalse # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseTrue # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue Recommended.Editions_Proto2.JsonInput.BoolMapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Editions_Proto2.JsonInput.DoubleFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Editions_Proto2.JsonInput.DoubleFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted Recommended.Editions_Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1
Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Editions_Proto2.JsonInput.FloatFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameDuplicate Recommended.Editions_Proto2.JsonInput.FloatFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FieldNameNotQuoted Recommended.Editions_Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted Recommended.Editions_Proto2.JsonInput.Int32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted Recommended.Editions_Proto2.JsonInput.Int64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted Recommended.Editions_Proto2.JsonInput.JsonWithComments # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.JsonWithComments Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth Recommended.Editions_Proto2.JsonInput.StringFieldSurrogateInWrongOrder # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedHighSurrogate # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedLowSurrogate # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder Recommended.Editions_Proto2.JsonInput.Uint32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Editions_Proto2.JsonInput.Uint64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Proto2.JsonInput.FieldNameExtension.Validator Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.EnumFieldNotQuoted Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.Int32FieldLeadingZero Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.Int32FieldPlusSign Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Required.Proto3.JsonInput.StringFieldNotAString Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldAllCapitalFalse Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldAllCapitalTrue Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldCamelCaseFalse Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldCamelCaseTrue Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.BoolMapFieldKeyNotQuoted Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.DoubleFieldInfinityNotQuoted Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.DoubleFieldNanNotQuoted Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameDuplicate Recommended.Editions_Proto3.JsonInput.JsonWithComments # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FieldNameNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FloatFieldInfinityNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FloatFieldNanNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.Int32MapFieldKeyNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.Int64MapFieldKeyNotQuoted Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.JsonWithComments Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey Recommended.Proto2.JsonInput.BoolFieldAllCapitalFalse # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue Recommended.Proto2.JsonInput.BoolFieldAllCapitalTrue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldSurrogateInWrongOrder Recommended.Proto2.JsonInput.BoolFieldCamelCaseFalse # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Proto2.JsonInput.BoolFieldCamelCaseTrue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.Uint32MapFieldKeyNotQuoted Recommended.Proto2.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Proto2.JsonInput.Uint64MapFieldKeyNotQuoted Recommended.Proto2.JsonInput.BoolMapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.EnumFieldNotQuoted Recommended.Proto2.JsonInput.DoubleFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.Int32FieldLeadingZero Recommended.Proto2.JsonInput.DoubleFieldNanNotQuoted # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.Int32FieldNegativeWithLeadingZero Recommended.Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.Int32FieldPlusSign Recommended.Proto2.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool Recommended.Proto2.JsonInput.FieldNameExtension.Validator # Expected JSON payload but got type 1
Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Recommended.Proto2.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Required.Proto2.JsonInput.StringFieldNotAString Recommended.Proto2.JsonInput.FloatFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput Recommended.Proto2.JsonInput.FloatFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput Recommended.Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput Recommended.Proto2.JsonInput.Int32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse Recommended.Proto2.JsonInput.Int64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue Recommended.Proto2.JsonInput.JsonWithComments # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse Recommended.Proto2.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue Recommended.Proto2.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Proto2.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue Recommended.Proto2.JsonInput.StringFieldSurrogateInWrongOrder # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted Recommended.Proto2.JsonInput.StringFieldUnpairedHighSurrogate # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted Recommended.Proto2.JsonInput.StringFieldUnpairedLowSurrogate # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted Recommended.Proto2.JsonInput.Uint32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted Recommended.Proto2.JsonInput.Uint64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput # Should have failed to serialize, but didn't.
Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted Recommended.Proto3.JsonInput.BoolFieldCamelCaseTrue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.JsonWithComments Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth Recommended.Proto3.JsonInput.BoolMapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey Recommended.Proto3.JsonInput.DoubleFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue Recommended.Proto3.JsonInput.DoubleFieldNanNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder Recommended.Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate Recommended.Proto3.JsonInput.FieldNameDuplicate # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted Recommended.Proto3.JsonInput.FieldNameNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted Recommended.Proto3.JsonInput.FloatFieldInfinityNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator Recommended.Proto3.JsonInput.FloatFieldNanNotQuoted # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted Recommended.Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero Recommended.Proto3.JsonInput.Int32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero Recommended.Proto3.JsonInput.Int64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.Int32FieldPlusSign Recommended.Proto3.JsonInput.JsonWithComments # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey # Should have failed to parse, but didn't.
Required.Editions_Proto3.JsonInput.StringFieldNotAString Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalFalse Recommended.Proto3.JsonInput.StringFieldSurrogateInWrongOrder # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldAllCapitalTrue Recommended.Proto3.JsonInput.StringFieldUnpairedHighSurrogate # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseFalse Recommended.Proto3.JsonInput.StringFieldUnpairedLowSurrogate # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldCamelCaseTrue Recommended.Proto3.JsonInput.Uint32MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedFalse Recommended.Proto3.JsonInput.Uint64MapFieldKeyNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolFieldDoubleQuotedTrue Required.Editions_Proto2.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.BoolMapFieldKeyNotQuoted Required.Editions_Proto2.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.DoubleFieldInfinityNotQuoted Required.Editions_Proto2.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.DoubleFieldNanNotQuoted Required.Editions_Proto2.JsonInput.Int32FieldPlusSign # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.DoubleFieldNegativeInfinityNotQuoted Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameDuplicate Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FieldNameNotQuoted Required.Editions_Proto2.JsonInput.StringFieldNotAString # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FloatFieldInfinityNotQuoted Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Recommended.Editions_Proto2.JsonInput.FloatFieldNanNotQuoted Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.FloatFieldNegativeInfinityNotQuoted Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.Int32MapFieldKeyNotQuoted Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.Int64MapFieldKeyNotQuoted Required.Editions_Proto3.JsonInput.Int32FieldPlusSign # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.JsonWithComments Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteBoth Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteKey Required.Editions_Proto3.JsonInput.StringFieldNotAString # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldSingleQuoteValue Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Recommended.Editions_Proto2.JsonInput.StringFieldSurrogateInWrongOrder Required.Proto2.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedHighSurrogate Required.Proto2.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.StringFieldUnpairedLowSurrogate Required.Proto2.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.Uint32MapFieldKeyNotQuoted Required.Proto2.JsonInput.Int32FieldPlusSign # Should have failed to parse, but didn't.
Recommended.Editions_Proto2.JsonInput.Uint64MapFieldKeyNotQuoted Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.EnumFieldNotQuoted Required.Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.Int32FieldLeadingZero Required.Proto2.JsonInput.StringFieldNotAString # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.Int32FieldNegativeWithLeadingZero Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Required.Editions_Proto2.JsonInput.Int32FieldPlusSign Required.Proto3.JsonInput.EnumFieldNotQuoted # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool Required.Proto3.JsonInput.Int32FieldLeadingZero # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt Required.Proto3.JsonInput.Int32FieldNegativeWithLeadingZero # Should have failed to parse, but didn't.
Required.Editions_Proto2.JsonInput.StringFieldNotAString Required.Proto3.JsonInput.Int32FieldPlusSign # Should have failed to parse, but didn't.
Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool # Should have failed to parse, but didn't.
Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt # Should have failed to parse, but didn't.
Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.JsonInput.StringFieldNotAString # Should have failed to parse, but didn't.
Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch

@ -4,11 +4,11 @@
# By listing them here we can keep tabs on which ones are failing and be sure # By listing them here we can keep tabs on which ones are failing and be sure
# that we don't introduce regressions in other tests. # that we don't introduce regressions in other tests.
Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Editions_Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownNonRepeatedValue.MESSAGE # Should have failed to parse, but didn't.
Required.Editions_Proto2.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE Required.Proto3.ProtobufInput.PrematureEofInDelimitedDataForKnownRepeatedValue.MESSAGE # Should have failed to parse, but didn't.

@ -1,7 +1,7 @@
# JSON input or output tests are skipped (in conformance_objc.m) as mobile # JSON input or output tests are skipped (in conformance_objc.m) as mobile
# platforms don't support JSON wire format to avoid code bloat. # platforms don't support JSON wire format to avoid code bloat.
Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Editions_Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Editions_Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto2.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch
Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput Required.Proto3.ProtobufInput.UnknownOrdering.ProtobufOutput # Unknown field mismatch

@ -26,6 +26,7 @@
using conformance::ConformanceRequest; using conformance::ConformanceRequest;
using conformance::ConformanceResponse; using conformance::ConformanceResponse;
using conformance::TestStatus;
using conformance::WireFormat; using conformance::WireFormat;
using protobuf_test_messages::editions::TestAllTypesEdition2023; using protobuf_test_messages::editions::TestAllTypesEdition2023;
using protobuf_test_messages::proto2::TestAllTypesProto2; using protobuf_test_messages::proto2::TestAllTypesProto2;
@ -73,19 +74,22 @@ bool TextFormatConformanceTestSuite::ParseResponse(
const std::string& test_name = setting.GetTestName(); const std::string& test_name = setting.GetTestName();
ConformanceLevel level = setting.GetLevel(); ConformanceLevel level = setting.GetLevel();
TestStatus test;
test.set_name(test_name);
switch (response.result_case()) { switch (response.result_case()) {
case ConformanceResponse::kProtobufPayload: { case ConformanceResponse::kProtobufPayload: {
if (requested_output != conformance::PROTOBUF) { if (requested_output != conformance::PROTOBUF) {
ReportFailure(test_name, level, request, response, test.set_failure_message(absl::StrCat(
absl::StrCat("Test was asked for ", "Test was asked for ", WireFormatToString(requested_output),
WireFormatToString(requested_output),
" output but provided PROTOBUF instead.")); " output but provided PROTOBUF instead."));
ReportFailure(test, level, request, response);
return false; return false;
} }
if (!test_message->ParseFromString(response.protobuf_payload())) { if (!test_message->ParseFromString(response.protobuf_payload())) {
ReportFailure(test_name, level, request, response, test.set_failure_message(
"Protobuf output we received from test was unparseable."); "Protobuf output we received from test was unparseable.");
ReportFailure(test, level, request, response);
return false; return false;
} }
@ -94,18 +98,17 @@ bool TextFormatConformanceTestSuite::ParseResponse(
case ConformanceResponse::kTextPayload: { case ConformanceResponse::kTextPayload: {
if (requested_output != conformance::TEXT_FORMAT) { if (requested_output != conformance::TEXT_FORMAT) {
ReportFailure( test.set_failure_message(absl::StrCat(
test_name, level, request, response, "Test was asked for ", WireFormatToString(requested_output),
absl::StrCat("Test was asked for ",
WireFormatToString(requested_output),
" output but provided TEXT_FORMAT instead.")); " output but provided TEXT_FORMAT instead."));
ReportFailure(test, level, request, response);
return false; return false;
} }
if (!ParseTextFormatResponse(response, setting, test_message)) { if (!ParseTextFormatResponse(response, setting, test_message)) {
ReportFailure( test.set_failure_message(
test_name, level, request, response,
"TEXT_FORMAT output we received from test was unparseable."); "TEXT_FORMAT output we received from test was unparseable.");
ReportFailure(test, level, request, response);
return false; return false;
} }
@ -172,14 +175,19 @@ void TextFormatConformanceTestSuiteImpl<MessageType>::ExpectParseFailure(
setting.ConformanceLevelToString(level), ".", setting.ConformanceLevelToString(level), ".",
setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name); setting.GetSyntaxIdentifier(), ".TextFormatInput.", test_name);
suite_.RunTest(effective_test_name, request, &response); if (!suite_.RunTest(effective_test_name, request, &response)) {
return;
}
TestStatus test;
test.set_name(effective_test_name);
if (response.result_case() == ConformanceResponse::kParseError) { if (response.result_case() == ConformanceResponse::kParseError) {
suite_.ReportSuccess(effective_test_name); suite_.ReportSuccess(test);
} else if (response.result_case() == ConformanceResponse::kSkipped) { } else if (response.result_case() == ConformanceResponse::kSkipped) {
suite_.ReportSkip(effective_test_name, request, response); suite_.ReportSkip(test, request, response);
} else { } else {
suite_.ReportFailure(effective_test_name, level, request, response, test.set_failure_message("Should have failed to parse, but didn't.");
"Should have failed to parse, but didn't."); suite_.ReportFailure(test, level, request, response);
} }
} }

@ -1,40 +1,42 @@
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString # Should have failed to parse, but didn't.
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes # Should have failed to parse, but didn't.
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString # Should have failed to parse, but didn't.
# End up setting the high bit as a sign instead of failing to parse.

@ -1,20 +1,20 @@
Recommended.Editions_Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput Recommended.Editions_Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Editions_Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput Recommended.Editions_Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Editions_Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput Recommended.Editions_Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Editions_Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput Recommended.Editions_Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput Recommended.Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput Recommended.Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput # TEXT_FORMAT output we received from test was unparseable.
Required.Editions_Proto3.TextFormatInput.AnyField.ProtobufOutput Required.Editions_Proto3.TextFormatInput.AnyField.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.AnyField.TextFormatOutput Required.Editions_Proto3.TextFormatInput.AnyField.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.AnyField.ProtobufOutput Required.Proto3.TextFormatInput.AnyField.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.AnyField.TextFormatOutput Required.Proto3.TextFormatInput.AnyField.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldNoOctal Required.Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal # Should have failed to parse, but didn't.

@ -1,99 +1,101 @@
# This is the list of text format conformance tests that are known to fail right # This is the list of text format conformance tests that are known to fail right
# now. # now.
# TODO: These should be fixed. # TODO: These should be fixed.
Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_f.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_f.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_f.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_f.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Editions_Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_double: -0
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Editions_Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_double: -0
Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatFieldMaxValue_f.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_f.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_f.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_f.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoOctal Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_f.ProtobufOutput Required.Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_double: -0
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_f.TextFormatOutput Required.Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_double: -0
Required.Editions_Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput Required.Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput Required.Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput # Output was not equivalent to reference message: deleted: optional_float: -0
Required.Editions_Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Editions_Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.FloatFieldNegativeZero.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatFieldNegativeZero.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Optional float interpreted as `inf`
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_f.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_f.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_f.ProtobufOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.NegDoubleFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_f.TextFormatOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue.ProtobufOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.NegFloatFieldLargeNegativeExponentParsesAsNegZero.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue.TextFormatOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.FloatFieldMaxValue_f.ProtobufOutput # Output was not equivalent to reference message
Required.Proto3.TextFormatInput.FloatFieldMaxValue_f.TextFormatOutput # Output was not equivalent to reference message

@ -1,72 +1,72 @@
Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldNoOctal Required.Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\

@ -1,75 +1,75 @@
# This is the list of text format conformance tests that are known to fail right # This is the list of text format conformance tests that are known to fail right
# now. # now.
# TODO: These should be fixed. # TODO: These should be fixed.
Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldNoOctal Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Editions_Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Editions_Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanInt64_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldLargerThanUint64_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMaxValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldMinValue_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNegative_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNegative_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNegativeZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoLeadingZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldNoLeadingZeroWithExponent_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldNoOctal # Should have failed to parse, but didn't.
Required.Proto3.TextFormatInput.FloatFieldNoNegativeOctal Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldNoOctal Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooLarge_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldTooSmall_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithInt32Max_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldWithVeryPreciseNumber_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.ProtobufOutput Required.Proto3.TextFormatInput.FloatField_F.ProtobufOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.FloatFieldZero_F.TextFormatOutput Required.Proto3.TextFormatInput.FloatField_F.TextFormatOutput # Failed to parse input or produce output.
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.ProtobufOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesBytes.TextFormatOutput # Output was not equivalent to reference message: modified: optional_bytes: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\t
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.ProtobufOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\
Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput Required.Proto3.TextFormatInput.StringLiteralBasicEscapesString.TextFormatOutput # Output was not equivalent to reference message: modified: optional_string: "\007\010\014\n\r\t\013?\\\'\"" -> "\007\010\014\n\r\

@ -8,6 +8,14 @@
"""Script to update a failure list file to add/remove failures. """Script to update a failure list file to add/remove failures.
When adding, will attempt to place them in their correct lexicographical
position relative to other test names. This requires that the failure list is
already sorted. This does not guarantee that the tests will appear neatly one
after the other, as there may be comments in between. If the failure list
is not sorted, sorted blocks may be produced, but the list as a whole will not.
Lastly, be wary of lists that have tests stripped from OSS; if you catch that
a test was added inside a stripped block, you may need to move it out.
This is sort of like comm(1), except it recognizes comments and ignores them. This is sort of like comm(1), except it recognizes comments and ignores them.
""" """
@ -19,32 +27,58 @@ parser.add_argument('filename', type=str, help='failure list file to update')
parser.add_argument('--add', dest='add_list', action='append') parser.add_argument('--add', dest='add_list', action='append')
parser.add_argument('--remove', dest='remove_list', action='append') parser.add_argument('--remove', dest='remove_list', action='append')
DEFAULT_ALIGNMENT = 114
args = parser.parse_args() args = parser.parse_args()
add_set = set() add_set = set()
remove_set = set() remove_set = set()
# Adds test + failure message
for add_file in (args.add_list or []): for add_file in (args.add_list or []):
with open(add_file) as f: with open(add_file) as f:
for line in f: for line in f:
add_set.add(line) add_set.add(line)
# We only remove by name
for remove_file in (args.remove_list or []): for remove_file in (args.remove_list or []):
with open(remove_file) as f: with open(remove_file) as f:
for line in f: for line in f:
if line in add_set: if line in add_set:
raise Exception("Asked to both add and remove test: " + line) raise Exception("Asked to both add and remove test: " + line)
remove_set.add(line.strip()) remove_set.add(line.split('#')[0].strip())
add_list = sorted(add_set, reverse=True) add_list = sorted(add_set, reverse=True)
with open(args.filename) as in_file: with open(args.filename) as in_file:
existing_list = in_file.read() existing_list = in_file.read()
with open(args.filename, "w") as f: with open(args.filename, 'w') as f:
for line in existing_list.splitlines(True): for line in existing_list.splitlines(True):
test = line.split("#")[0].strip() test = line.split('#')[0].strip()
while len(add_list) > 0 and test > add_list[-1]: # As long as the tests we are adding appear lexicographically before our
# read test, put them first followed by our read test.
while add_list and test > add_list[-1]:
f.write(add_list.pop()) f.write(add_list.pop())
if test not in remove_set: if test not in remove_set:
f.write(line) f.write(line)
# Any remaining tests are added at the end
while add_list:
f.write(add_list.pop())
# Update our read of the existing file
with open(args.filename, 'r') as f:
existing_list = f.read()
# Actual alignment of failure messages to 'DEFAULT_ALIGNMENT'
# If test name exceeds DEFAULT_ALIGNMENT, it cannot and will not be aligned.
with open(args.filename, 'w') as f:
for line in existing_list.splitlines(True):
split = line.split('#', 1)
test = split[0].strip()
if len(split) > 1 and test:
message = split[1].lstrip()
spaces = ' ' * (DEFAULT_ALIGNMENT - len(test))
line = test + spaces + ' # ' + message
f.write(line)
else: # ignore blank lines/lines that do not have '#'/comments
f.write(line)

@ -25,32 +25,35 @@ namespace Conformance {
byte[] descriptorData = global::System.Convert.FromBase64String( byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat( string.Concat(
"Ch1jb25mb3JtYW5jZS9jb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2Ui", "Ch1jb25mb3JtYW5jZS9jb25mb3JtYW5jZS5wcm90bxILY29uZm9ybWFuY2Ui",
"HQoKRmFpbHVyZVNldBIPCgdmYWlsdXJlGAEgAygJIuMCChJDb25mb3JtYW5j", "MwoKVGVzdFN0YXR1cxIMCgRuYW1lGAEgASgJEhcKD2ZhaWx1cmVfbWVzc2Fn",
"ZVJlcXVlc3QSGgoQcHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25f", "ZRgCIAEoCSI5CgpGYWlsdXJlU2V0EiUKBHRlc3QYAiADKAsyFy5jb25mb3Jt",
"cGF5bG9hZBgCIAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRl", "YW5jZS5UZXN0U3RhdHVzSgQIARACIuMCChJDb25mb3JtYW5jZVJlcXVlc3QS",
"eHRfcGF5bG9hZBgIIAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0", "GgoQcHJvdG9idWZfcGF5bG9hZBgBIAEoDEgAEhYKDGpzb25fcGF5bG9hZBgC",
"GAMgASgOMhcuY29uZm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5", "IAEoCUgAEhYKDGpzcGJfcGF5bG9hZBgHIAEoCUgAEhYKDHRleHRfcGF5bG9h",
"cGUYBCABKAkSMAoNdGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNl", "ZBgIIAEoCUgAEjgKF3JlcXVlc3RlZF9vdXRwdXRfZm9ybWF0GAMgASgOMhcu",
"LlRlc3RDYXRlZ29yeRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsy", "Y29uZm9ybWFuY2UuV2lyZUZvcm1hdBIUCgxtZXNzYWdlX3R5cGUYBCABKAkS",
"Hy5jb25mb3JtYW5jZS5Kc3BiRW5jb2RpbmdDb25maWcSHAoUcHJpbnRfdW5r", "MAoNdGVzdF9jYXRlZ29yeRgFIAEoDjIZLmNvbmZvcm1hbmNlLlRlc3RDYXRl",
"bm93bl9maWVsZHMYCSABKAhCCQoHcGF5bG9hZCL6AQoTQ29uZm9ybWFuY2VS", "Z29yeRI+ChVqc3BiX2VuY29kaW5nX29wdGlvbnMYBiABKAsyHy5jb25mb3Jt",
"ZXNwb25zZRIVCgtwYXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9l", "YW5jZS5Kc3BiRW5jb2RpbmdDb25maWcSHAoUcHJpbnRfdW5rbm93bl9maWVs",
"cnJvchgGIAEoCUgAEhcKDXRpbWVvdXRfZXJyb3IYCSABKAlIABIXCg1ydW50", "ZHMYCSABKAhCCQoHcGF5bG9hZCL6AQoTQ29uZm9ybWFuY2VSZXNwb25zZRIV",
"aW1lX2Vycm9yGAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgDIAEoDEgA", "CgtwYXJzZV9lcnJvchgBIAEoCUgAEhkKD3NlcmlhbGl6ZV9lcnJvchgGIAEo",
"EhYKDGpzb25fcGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSABKAlIABIW", "CUgAEhcKDXRpbWVvdXRfZXJyb3IYCSABKAlIABIXCg1ydW50aW1lX2Vycm9y",
"Cgxqc3BiX3BheWxvYWQYByABKAlIABIWCgx0ZXh0X3BheWxvYWQYCCABKAlI", "GAIgASgJSAASGgoQcHJvdG9idWZfcGF5bG9hZBgDIAEoDEgAEhYKDGpzb25f",
"AEIICgZyZXN1bHQiNwoSSnNwYkVuY29kaW5nQ29uZmlnEiEKGXVzZV9qc3Bi", "cGF5bG9hZBgEIAEoCUgAEhEKB3NraXBwZWQYBSABKAlIABIWCgxqc3BiX3Bh",
"X2FycmF5X2FueV9mb3JtYXQYASABKAgqUAoKV2lyZUZvcm1hdBIPCgtVTlNQ", "eWxvYWQYByABKAlIABIWCgx0ZXh0X3BheWxvYWQYCCABKAlIAEIICgZyZXN1",
"RUNJRklFRBAAEgwKCFBST1RPQlVGEAESCAoESlNPThACEggKBEpTUEIQAxIP", "bHQiNwoSSnNwYkVuY29kaW5nQ29uZmlnEiEKGXVzZV9qc3BiX2FycmF5X2Fu",
"CgtURVhUX0ZPUk1BVBAEKo8BCgxUZXN0Q2F0ZWdvcnkSFAoQVU5TUEVDSUZJ", "eV9mb3JtYXQYASABKAgqUAoKV2lyZUZvcm1hdBIPCgtVTlNQRUNJRklFRBAA",
"RURfVEVTVBAAEg8KC0JJTkFSWV9URVNUEAESDQoJSlNPTl9URVNUEAISJAog", "EgwKCFBST1RPQlVGEAESCAoESlNPThACEggKBEpTUEIQAxIPCgtURVhUX0ZP",
"SlNPTl9JR05PUkVfVU5LTk9XTl9QQVJTSU5HX1RFU1QQAxINCglKU1BCX1RF", "Uk1BVBAEKo8BCgxUZXN0Q2F0ZWdvcnkSFAoQVU5TUEVDSUZJRURfVEVTVBAA",
"U1QQBBIUChBURVhUX0ZPUk1BVF9URVNUEAVCLwofY29tLmdvb2dsZS5wcm90", "Eg8KC0JJTkFSWV9URVNUEAESDQoJSlNPTl9URVNUEAISJAogSlNPTl9JR05P",
"b2J1Zi5jb25mb3JtYW5jZaICC0NvbmZvcm1hbmNlYgZwcm90bzM=")); "UkVfVU5LTk9XTl9QQVJTSU5HX1RFU1QQAxINCglKU1BCX1RFU1QQBBIUChBU",
"RVhUX0ZPUk1BVF9URVNUEAVCLwofY29tLmdvb2dsZS5wcm90b2J1Zi5jb25m",
"b3JtYW5jZaICC0NvbmZvcm1hbmNlYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { }, new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(new[] {typeof(global::Conformance.WireFormat), typeof(global::Conformance.TestCategory), }, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Failure" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.TestStatus), global::Conformance.TestStatus.Parser, new[]{ "Name", "FailureMessage" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.FailureSet), global::Conformance.FailureSet.Parser, new[]{ "Test" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions", "PrintUnknownFields" }, new[]{ "Payload" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceRequest), global::Conformance.ConformanceRequest.Parser, new[]{ "ProtobufPayload", "JsonPayload", "JspbPayload", "TextPayload", "RequestedOutputFormat", "MessageType", "TestCategory", "JspbEncodingOptions", "PrintUnknownFields" }, new[]{ "Payload" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "TimeoutError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.ConformanceResponse), global::Conformance.ConformanceResponse.Parser, new[]{ "ParseError", "SerializeError", "TimeoutError", "RuntimeError", "ProtobufPayload", "JsonPayload", "Skipped", "JspbPayload", "TextPayload" }, new[]{ "Result" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null, null) new pbr::GeneratedClrTypeInfo(typeof(global::Conformance.JspbEncodingConfig), global::Conformance.JspbEncodingConfig.Parser, new[]{ "UseJspbArrayAnyFormat" }, null, null, null, null)
@ -104,6 +107,246 @@ namespace Conformance {
#endregion #endregion
#region Messages #region Messages
/// <summary>
/// Meant to encapsulate all types of tests: successes, skips, failures, etc.
/// Therefore, this may or may not have a failure message. Failure messages
/// may be truncated for our failure lists.
/// </summary>
[global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")]
public sealed partial class TestStatus : pb::IMessage<TestStatus>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<TestStatus> _parser = new pb::MessageParser<TestStatus>(() => new TestStatus());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<TestStatus> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public TestStatus() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public TestStatus(TestStatus other) : this() {
name_ = other.name_;
failureMessage_ = other.failureMessage_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public TestStatus Clone() {
return new TestStatus(this);
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 1;
private string name_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "failure_message" field.</summary>
public const int FailureMessageFieldNumber = 2;
private string failureMessage_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string FailureMessage {
get { return failureMessage_; }
set {
failureMessage_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as TestStatus);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(TestStatus other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Name != other.Name) return false;
if (FailureMessage != other.FailureMessage) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (FailureMessage.Length != 0) hash ^= FailureMessage.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (FailureMessage.Length != 0) {
output.WriteRawTag(18);
output.WriteString(FailureMessage);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (FailureMessage.Length != 0) {
output.WriteRawTag(18);
output.WriteString(FailureMessage);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (FailureMessage.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(FailureMessage);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(TestStatus other) {
if (other == null) {
return;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
if (other.FailureMessage.Length != 0) {
FailureMessage = other.FailureMessage;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Name = input.ReadString();
break;
}
case 18: {
FailureMessage = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
if ((tag & 7) == 4) {
// Abort on any end group tag.
return;
}
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
Name = input.ReadString();
break;
}
case 18: {
FailureMessage = input.ReadString();
break;
}
}
}
}
#endif
}
/// <summary> /// <summary>
/// The conformance runner will request a list of failures as the first request. /// The conformance runner will request a list of failures as the first request.
/// This will be known by message_type == "conformance.FailureSet", a conformance /// This will be known by message_type == "conformance.FailureSet", a conformance
@ -124,7 +367,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[0]; } get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -144,7 +387,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public FailureSet(FailureSet other) : this() { public FailureSet(FailureSet other) : this() {
failure_ = other.failure_.Clone(); test_ = other.test_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
} }
@ -154,15 +397,15 @@ namespace Conformance {
return new FailureSet(this); return new FailureSet(this);
} }
/// <summary>Field number for the "failure" field.</summary> /// <summary>Field number for the "test" field.</summary>
public const int FailureFieldNumber = 1; public const int TestFieldNumber = 2;
private static readonly pb::FieldCodec<string> _repeated_failure_codec private static readonly pb::FieldCodec<global::Conformance.TestStatus> _repeated_test_codec
= pb::FieldCodec.ForString(10); = pb::FieldCodec.ForMessage(18, global::Conformance.TestStatus.Parser);
private readonly pbc::RepeatedField<string> failure_ = new pbc::RepeatedField<string>(); private readonly pbc::RepeatedField<global::Conformance.TestStatus> test_ = new pbc::RepeatedField<global::Conformance.TestStatus>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pbc::RepeatedField<string> Failure { public pbc::RepeatedField<global::Conformance.TestStatus> Test {
get { return failure_; } get { return test_; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -180,7 +423,7 @@ namespace Conformance {
if (ReferenceEquals(other, this)) { if (ReferenceEquals(other, this)) {
return true; return true;
} }
if(!failure_.Equals(other.failure_)) return false; if(!test_.Equals(other.test_)) return false;
return Equals(_unknownFields, other._unknownFields); return Equals(_unknownFields, other._unknownFields);
} }
@ -188,7 +431,7 @@ namespace Conformance {
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() { public override int GetHashCode() {
int hash = 1; int hash = 1;
hash ^= failure_.GetHashCode(); hash ^= test_.GetHashCode();
if (_unknownFields != null) { if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode(); hash ^= _unknownFields.GetHashCode();
} }
@ -207,7 +450,7 @@ namespace Conformance {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this); output.WriteRawMessage(this);
#else #else
failure_.WriteTo(output, _repeated_failure_codec); test_.WriteTo(output, _repeated_test_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
_unknownFields.WriteTo(output); _unknownFields.WriteTo(output);
} }
@ -218,7 +461,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
failure_.WriteTo(ref output, _repeated_failure_codec); test_.WriteTo(ref output, _repeated_test_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
_unknownFields.WriteTo(ref output); _unknownFields.WriteTo(ref output);
} }
@ -229,7 +472,7 @@ namespace Conformance {
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() { public int CalculateSize() {
int size = 0; int size = 0;
size += failure_.CalculateSize(_repeated_failure_codec); size += test_.CalculateSize(_repeated_test_codec);
if (_unknownFields != null) { if (_unknownFields != null) {
size += _unknownFields.CalculateSize(); size += _unknownFields.CalculateSize();
} }
@ -242,7 +485,7 @@ namespace Conformance {
if (other == null) { if (other == null) {
return; return;
} }
failure_.Add(other.failure_); test_.Add(other.test_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
} }
@ -262,8 +505,8 @@ namespace Conformance {
default: default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break; break;
case 10: { case 18: {
failure_.AddEntriesFrom(input, _repeated_failure_codec); test_.AddEntriesFrom(input, _repeated_test_codec);
break; break;
} }
} }
@ -285,8 +528,8 @@ namespace Conformance {
default: default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break; break;
case 10: { case 18: {
failure_.AddEntriesFrom(ref input, _repeated_failure_codec); test_.AddEntriesFrom(ref input, _repeated_test_codec);
break; break;
} }
} }
@ -318,7 +561,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[1]; } get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -945,7 +1188,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[2]; } get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@ -1665,7 +1908,7 @@ namespace Conformance {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor { public static pbr::MessageDescriptor Descriptor {
get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[3]; } get { return global::Conformance.ConformanceReflection.Descriptor.MessageTypes[4]; }
} }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]

@ -146,7 +146,11 @@ TEST(Generated, EditionDefaults2023InternalFeatures) {
utf8_validation: VERIFY utf8_validation: VERIFY
message_encoding: LENGTH_PREFIXED message_encoding: LENGTH_PREFIXED
json_format: ALLOW json_format: ALLOW
[pb.cpp] { legacy_closed_enum: false string_type: STRING } [pb.cpp] {
legacy_closed_enum: false
string_type: STRING
enum_name_uses_string_view: false
}
)pb")); )pb"));
} }

@ -30,9 +30,9 @@
{ {
- // optional int32 int32_field = 1; - // optional int32 int32_field = 1;
+ // int32 int32_field = 1; + // int32 int32_field = 1;
cached_has_bits = cached_has_bits = this_._impl_._has_bits_[0];
this_._impl_._has_bits_[0];
if (cached_has_bits & 0x00000001u) { if (cached_has_bits & 0x00000001u) {
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
[ FAILED ] third_party/protobuf/editions/golden/simple_proto3.pb.cc [ FAILED ] third_party/protobuf/editions/golden/simple_proto3.pb.cc
[ RUN ] third_party/protobuf/editions/golden/simple_proto3.pb.h [ RUN ] third_party/protobuf/editions/golden/simple_proto3.pb.h
@@ @@ @@ @@

@ -2,10 +2,10 @@
<testsuites tests="1" name="AllTests"> <testsuites tests="1" name="AllTests">
<testsuite name="EditionsCodegenTests"> <testsuite name="EditionsCodegenTests">
<testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.cc" status="run" result="completed" classname="DiffTest"> <testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.cc" status="run" result="completed" classname="DiffTest">
<failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.cc&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// NO CHECKED-IN PROTOBUF GENCODE&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;// Protobuf C++ Version: 0.20240712.0&#x0A;&#x0A;#include &quot;third_party/protobuf/editions/golden/simple_proto3.pb.h&quot;&#x0A;&#x0A;#include &lt;algorithm&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_impl.h&quot;&#x0A;#include &quot;third_party/protobuf/extension_set.h&quot;&#x0A;#include &quot;third_party/protobuf/wire_format_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/io/zero_copy_stream_impl_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;, with the difference:&#x0A;@@ @@&#x0A; ::_pbi::TcParser::GetTable&lt;::protobuf_editions_test::golden::SimpleProto3&gt;(), // to_prefetch&#x0A; #endif // PROTOBUF_PREFETCH_PARSE_TABLE&#x0A; }, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; {::_pbi::TcParser::FastV32S1,&#x0A; {8, 0, 0, PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_)}},&#x0A; }}, {{&#x0A; 65535, 65535&#x0A; }}, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; {PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_), _Internal::kHasBitsOffset + 0, 0,&#x0A; (0 | ::_fl::kFcOptional | ::_fl::kInt32)},&#x0A; }},&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; cached_has_bits = this_._impl_._has_bits_[0];&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; target = ::proto2::internal::WireFormatLite::&#x0A; WriteInt32ToArrayWithField&lt;1&gt;(&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; {&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; cached_has_bits =&#x0A; this_._impl_._has_bits_[0];&#x0A; if (cached_has_bits &amp; 0x00000001u) {" type=""></failure> <failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.cc&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// NO CHECKED-IN PROTOBUF GENCODE&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;// Protobuf C++ Version: 0.20240723.0&#x0A;&#x0A;#include &quot;third_party/protobuf/editions/golden/simple_proto3.pb.h&quot;&#x0A;&#x0A;#include &lt;algorithm&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_impl.h&quot;&#x0A;#include &quot;third_party/protobuf/extension_set.h&quot;&#x0A;#include &quot;third_party/protobuf/wire_format_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/io/zero_copy_stream_impl_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;, with the difference:&#x0A;@@ @@&#x0A; ::_pbi::TcParser::GetTable&lt;::protobuf_editions_test::golden::SimpleProto3&gt;(), // to_prefetch&#x0A; #endif // PROTOBUF_PREFETCH_PARSE_TABLE&#x0A; }, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; {::_pbi::TcParser::FastV32S1,&#x0A; {8, 0, 0, PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_)}},&#x0A; }}, {{&#x0A; 65535, 65535&#x0A; }}, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; {PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_), _Internal::kHasBitsOffset + 0, 0,&#x0A; (0 | ::_fl::kFcOptional | ::_fl::kInt32)},&#x0A; }},&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; cached_has_bits = this_._impl_._has_bits_[0];&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; target = ::proto2::internal::WireFormatLite::&#x0A; WriteInt32ToArrayWithField&lt;1&gt;(&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; {&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; cached_has_bits = this_._impl_._has_bits_[0];&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(" type=""></failure>
</testcase> </testcase>
<testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.h" status="run" result="completed" classname="DiffTest"> <testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.h" status="run" result="completed" classname="DiffTest">
<failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.h&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// NO CHECKED-IN PROTOBUF GENCODE&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;// Protobuf C++ Version: 0.20240712.0&#x0A;&#x0A;#ifndef GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;#define GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;&#x0A;#include &lt;limits&gt;&#x0A;#include &lt;string&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &lt;utility&gt;&#x0A;&#x0A;#include &quot;third_party/protobuf/runtime_version.h&quot;&#x0A;#if PROTOBUF_VERSION != 20240712&#x0A;#error &quot;Protobuf C++ gencode is built with an incompatible version of&quot;&#x0A;#error &quot;Protobuf C++ headers/runtime. See&quot;&#x0A;#error &quot;https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp&quot;&#x0A;#endif&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/arena.h&quot;&#x0A;#include &quot;third_party/protobuf/arenastring.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_decl.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_util.h&quot;&#x0A;#include &quot;third_party/protobuf/metadata_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/message_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;&#x0A;#endif // GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;, with the difference:&#x0A;@@ @@&#x0A; enum : int {&#x0A; kInt32FieldFieldNumber = 1,&#x0A; };&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; bool has_int32_field() const;&#x0A; void clear_int32_field() ;&#x0A; ::int32_t int32_field() const;&#x0A;@@ @@&#x0A; &#x0A; // SimpleProto3&#x0A; &#x0A;-// optional int32 int32_field = 1;&#x0A;+// int32 int32_field = 1;&#x0A; inline bool SimpleProto3::has_int32_field() const {&#x0A; bool value = (_impl_._has_bits_[0] &amp; 0x00000001u) != 0;&#x0A; return value;" type=""></failure> <failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.h&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// NO CHECKED-IN PROTOBUF GENCODE&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;// Protobuf C++ Version: 0.20240723.0&#x0A;&#x0A;#ifndef GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;#define GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;&#x0A;#include &lt;limits&gt;&#x0A;#include &lt;string&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &lt;utility&gt;&#x0A;&#x0A;#include &quot;third_party/protobuf/runtime_version.h&quot;&#x0A;#if PROTOBUF_VERSION != 20240723&#x0A;#error &quot;Protobuf C++ gencode is built with an incompatible version of&quot;&#x0A;#error &quot;Protobuf C++ headers/runtime. See&quot;&#x0A;#error &quot;https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp&quot;&#x0A;#endif&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/arena.h&quot;&#x0A;#include &quot;third_party/protobuf/arenastring.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_decl.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_util.h&quot;&#x0A;#include &quot;third_party/protobuf/metadata_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/message_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;&#x0A;#endif // GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;, with the difference:&#x0A;@@ @@&#x0A; enum : int {&#x0A; kInt32FieldFieldNumber = 1,&#x0A; };&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1;&#x0A; bool has_int32_field() const;&#x0A; void clear_int32_field() ;&#x0A; ::int32_t int32_field() const;&#x0A;@@ @@&#x0A; &#x0A; // SimpleProto3&#x0A; &#x0A;-// optional int32 int32_field = 1;&#x0A;+// int32 int32_field = 1;&#x0A; inline bool SimpleProto3::has_int32_field() const {&#x0A; bool value = (_impl_._has_bits_[0] &amp; 0x00000001u) != 0;&#x0A; return value;" type=""></failure>
</testcase> </testcase>
<testcase name="third_party/protobuf/editions/golden/simple_proto3.proto.static_reflection.h" status="run" result="completed" classname="DiffTest"> <testcase name="third_party/protobuf/editions/golden/simple_proto3.proto.static_reflection.h" status="run" result="completed" classname="DiffTest">
</testcase> </testcase>

@ -15,7 +15,7 @@ load(
) )
# begin:google_only # begin:google_only
# package(default_applicable_licenses = ["//upb:license"]) # package(default_applicable_licenses = ["//src/google/protobuf:license"])
# end:google_only # end:google_only
licenses(["notice"]) licenses(["notice"])

@ -36,11 +36,11 @@ std::string GenerateTestData() {
model.set_str1("str"); model.set_str1("str");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("theme"); extension1.set_ext_name("theme");
ABSL_CHECK_OK(::protos::SetExtension(&model, theme, extension1)); ABSL_CHECK_OK(::hpb::SetExtension(&model, theme, extension1));
ThemeExtension extension2; ThemeExtension extension2;
extension2.set_ext_name("theme_extension"); extension2.set_ext_name("theme_extension");
ABSL_CHECK_OK(::protos::SetExtension(&model, ThemeExtension::theme_extension, ABSL_CHECK_OK(
extension2)); ::hpb::SetExtension(&model, ThemeExtension::theme_extension, extension2));
::upb::Arena arena; ::upb::Arena arena;
auto bytes = ::protos::Serialize(&model, arena); auto bytes = ::protos::Serialize(&model, arena);
ABSL_CHECK_OK(bytes); ABSL_CHECK_OK(bytes);
@ -54,7 +54,7 @@ void unlock_func(const void* msg) { m[absl::HashOf(msg) & 0x7].unlock(); }
return &unlock_func; return &unlock_func;
} }
void TestConcurrentExtensionAccess(::protos::ExtensionRegistry registry) { void TestConcurrentExtensionAccess(::hpb::ExtensionRegistry registry) {
::hpb::internal::upb_extension_locker_global.store(&lock_func, ::hpb::internal::upb_extension_locker_global.store(&lock_func,
std::memory_order_release); std::memory_order_release);
const std::string payload = GenerateTestData(); const std::string payload = GenerateTestData();
@ -62,7 +62,7 @@ void TestConcurrentExtensionAccess(::protos::ExtensionRegistry registry) {
::protos::Parse<TestModel>(payload, registry).value(); ::protos::Parse<TestModel>(payload, registry).value();
const auto test_main = [&] { EXPECT_EQ("str", parsed_model.str1()); }; const auto test_main = [&] { EXPECT_EQ("str", parsed_model.str1()); };
const auto test_theme = [&] { const auto test_theme = [&] {
ASSERT_TRUE(::protos::HasExtension(&parsed_model, theme)); ASSERT_TRUE(::hpb::HasExtension(&parsed_model, theme));
auto ext = ::protos::GetExtension(&parsed_model, theme); auto ext = ::protos::GetExtension(&parsed_model, theme);
ASSERT_OK(ext); ASSERT_OK(ext);
EXPECT_EQ((*ext)->ext_name(), "theme"); EXPECT_EQ((*ext)->ext_name(), "theme");

@ -27,7 +27,7 @@
#include "upb/wire/decode.h" #include "upb/wire/decode.h"
#include "upb/wire/encode.h" #include "upb/wire/encode.h"
namespace protos { namespace hpb {
// begin:google_only // begin:google_only
absl::Status MessageAllocationError(SourceLocation loc) { absl::Status MessageAllocationError(SourceLocation loc) {
@ -83,10 +83,6 @@ absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc
namespace internal { namespace internal {
using ::hpb::internal::upb_extension_locker_global;
using ::hpb::internal::UpbExtensionLocker;
using ::hpb::internal::UpbExtensionUnlocker;
upb_ExtensionRegistry* GetUpbExtensions( upb_ExtensionRegistry* GetUpbExtensions(
const ExtensionRegistry& extension_registry) { const ExtensionRegistry& extension_registry) {
return extension_registry.registry_; return extension_registry.registry_;
@ -186,4 +182,4 @@ absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena,
} // namespace internal } // namespace internal
} // namespace protos } // namespace hpb

@ -8,11 +8,13 @@
#ifndef PROTOBUF_HPB_HPB_H_ #ifndef PROTOBUF_HPB_HPB_H_
#define PROTOBUF_HPB_HPB_H_ #define PROTOBUF_HPB_HPB_H_
#include <cstdint>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
#include "absl/status/status.h" #include "absl/status/status.h"
#include "absl/status/statusor.h" #include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "upb/base/status.hpp" #include "upb/base/status.hpp"
#include "upb/mem/arena.hpp" #include "upb/mem/arena.hpp"
#include "upb/message/copy.h" #include "upb/message/copy.h"
@ -21,12 +23,8 @@
#include "upb/wire/encode.h" #include "upb/wire/encode.h"
namespace hpb { namespace hpb {
using Arena = ::upb::Arena;
}
namespace protos {
using hpb::Arena;
class ExtensionRegistry; class ExtensionRegistry;
using Arena = ::upb::Arena;
template <typename T> template <typename T>
using Proxy = std::conditional_t<std::is_const<T>::value, using Proxy = std::conditional_t<std::is_const<T>::value,
@ -85,6 +83,7 @@ class Ptr final {
template <typename T> template <typename T>
Ptr(T* m) -> Ptr<T>; Ptr(T* m) -> Ptr<T>;
// TODO: b/354766950 - Move upb-specific chunks out of hpb header
inline absl::string_view UpbStrToStringView(upb_StringView str) { inline absl::string_view UpbStrToStringView(upb_StringView str) {
return absl::string_view(str.data, str.size); return absl::string_view(str.data, str.size);
} }
@ -98,12 +97,6 @@ inline upb_StringView UpbStrFromStringView(absl::string_view str,
return upb_StringView_FromDataAndSize(buffer, str_size); return upb_StringView_FromDataAndSize(buffer, str_size);
} }
template <typename T>
typename T::Proxy CreateMessage(::protos::Arena& arena) {
return typename T::Proxy(upb_Message_New(T::minitable(), arena.ptr()),
arena.ptr());
}
// begin:github_only // begin:github_only
// // This type exists to work around an absl type that has not yet been // // This type exists to work around an absl type that has not yet been
// // released. // // released.
@ -131,6 +124,34 @@ absl::Status MessageEncodeError(upb_EncodeStatus status,
SourceLocation loc = SourceLocation::current()); SourceLocation loc = SourceLocation::current());
namespace internal { namespace internal {
template <typename T>
struct RemovePtr;
template <typename T>
struct RemovePtr<Ptr<T>> {
using type = T;
};
template <typename T>
struct RemovePtr<T*> {
using type = T;
};
template <typename T>
using RemovePtrT = typename RemovePtr<T>::type;
template <typename T, typename U = RemovePtrT<T>,
typename = std::enable_if_t<!std::is_const_v<U>>>
using PtrOrRaw = T;
template <typename T>
using EnableIfHpbClass = std::enable_if_t<
std::is_base_of<typename T::Access, T>::value &&
std::is_base_of<typename T::Access, typename T::ExtendableType>::value>;
template <typename T>
using EnableIfMutableProto = std::enable_if_t<!std::is_const<T>::value>;
struct PrivateAccess { struct PrivateAccess {
template <typename T> template <typename T>
static auto* GetInternalMsg(T&& message) { static auto* GetInternalMsg(T&& message) {
@ -148,6 +169,11 @@ struct PrivateAccess {
static auto CreateMessage(upb_Arena* arena) { static auto CreateMessage(upb_Arena* arena) {
return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena); return typename T::Proxy(upb_Message_New(T::minitable(), arena), arena);
} }
template <typename ExtensionId>
static constexpr uint32_t GetExtensionNumber(const ExtensionId& id) {
return id.number();
}
}; };
template <typename T> template <typename T>
@ -200,6 +226,12 @@ class ExtensionIdentifier : public ExtensionMiniTableProvider {
constexpr explicit ExtensionIdentifier( constexpr explicit ExtensionIdentifier(
const upb_MiniTableExtension* mini_table_ext) const upb_MiniTableExtension* mini_table_ext)
: ExtensionMiniTableProvider(mini_table_ext) {} : ExtensionMiniTableProvider(mini_table_ext) {}
private:
constexpr uint32_t number() const {
return upb_MiniTableExtension_Number(mini_table_ext());
}
friend class PrivateAccess;
}; };
template <typename T> template <typename T>
@ -249,82 +281,12 @@ absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena,
const upb_MiniTableExtension* ext, const upb_MiniTableExtension* ext,
const upb_Message* extension); const upb_Message* extension);
template <typename T>
struct RemovePtr;
template <typename T>
struct RemovePtr<Ptr<T>> {
using type = T;
};
template <typename T>
struct RemovePtr<T*> {
using type = T;
};
template <typename T>
using RemovePtrT = typename RemovePtr<T>::type;
template <typename T, typename U = RemovePtrT<T>,
typename = std::enable_if_t<!std::is_const_v<U>>>
using PtrOrRaw = T;
template <typename T>
using EnableIfHpbClass = std::enable_if_t<
std::is_base_of<typename T::Access, T>::value &&
std::is_base_of<typename T::Access, typename T::ExtendableType>::value>;
template <typename T>
using EnableIfMutableProto = std::enable_if_t<!std::is_const<T>::value>;
} // namespace internal } // namespace internal
template <typename T>
void DeepCopy(Ptr<const T> source_message, Ptr<T> target_message) {
static_assert(!std::is_const_v<T>);
::protos::internal::DeepCopy(
internal::GetInternalMsg(target_message),
internal::GetInternalMsg(source_message), T::minitable(),
static_cast<upb_Arena*>(target_message->GetInternalArena()));
}
template <typename T>
typename T::Proxy CloneMessage(Ptr<T> message, upb_Arena* arena) {
return internal::PrivateAccess::Proxy<T>(
::protos::internal::DeepClone(internal::GetInternalMsg(message),
T::minitable(), arena),
arena);
}
template <typename T>
void DeepCopy(Ptr<const T> source_message, T* target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(source_message, protos::Ptr(target_message));
}
template <typename T>
void DeepCopy(const T* source_message, Ptr<T> target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(protos::Ptr(source_message), target_message);
}
template <typename T>
void DeepCopy(const T* source_message, T* target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(protos::Ptr(source_message), protos::Ptr(target_message));
}
template <typename T>
void ClearMessage(internal::PtrOrRaw<T> message) {
auto ptr = Ptr(message);
auto minitable = internal::GetMiniTable(ptr);
upb_Message_Clear(internal::GetInternalMsg(ptr), minitable);
}
class ExtensionRegistry { class ExtensionRegistry {
public: public:
ExtensionRegistry( ExtensionRegistry(
const std::vector<const ::protos::internal::ExtensionMiniTableProvider*>& const std::vector<const internal::ExtensionMiniTableProvider*>&
extensions, extensions,
const upb::Arena& arena) const upb::Arena& arena)
: registry_(upb_ExtensionRegistry_New(arena.ptr())) { : registry_(upb_ExtensionRegistry_New(arena.ptr())) {
@ -341,151 +303,209 @@ class ExtensionRegistry {
} }
private: private:
friend upb_ExtensionRegistry* ::protos::internal::GetUpbExtensions( friend upb_ExtensionRegistry* ::hpb::internal::GetUpbExtensions(
const ExtensionRegistry& extension_registry); const ExtensionRegistry& extension_registry);
upb_ExtensionRegistry* registry_; upb_ExtensionRegistry* registry_;
}; };
template <typename T, typename Extendee, typename Extension, template <typename T, typename Extendee, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
ABSL_MUST_USE_RESULT bool HasExtension( ABSL_MUST_USE_RESULT bool HasExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) { const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
return ::protos::internal::HasExtensionOrUnknown( return ::hpb::internal::HasExtensionOrUnknown(
::protos::internal::GetInternalMsg(message), id.mini_table_ext()); ::hpb::internal::GetInternalMsg(message), id.mini_table_ext());
} }
template <typename T, typename Extendee, typename Extension, template <typename T, typename Extendee, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
ABSL_MUST_USE_RESULT bool HasExtension( ABSL_MUST_USE_RESULT bool HasExtension(
const T* message, const T* message,
const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) { const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
return HasExtension(protos::Ptr(message), id); return HasExtension(Ptr(message), id);
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>, typename = hpb::internal::EnableIfHpbClass<T>,
typename = internal::EnableIfMutableProto<T>> typename = hpb::internal::EnableIfMutableProto<T>>
void ClearExtension( void ClearExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<T, Extension>& id) { const ::hpb::internal::ExtensionIdentifier<T, Extension>& id) {
static_assert(!std::is_const_v<T>, ""); static_assert(!std::is_const_v<T>, "");
upb_Message_ClearExtension(internal::GetInternalMsg(message), upb_Message_ClearExtension(hpb::internal::GetInternalMsg(message),
id.mini_table_ext()); id.mini_table_ext());
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
void ClearExtension( void ClearExtension(
T* message, T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id) {
const ::protos::internal::ExtensionIdentifier<T, Extension>& id) { ClearExtension(Ptr(message), id);
ClearExtension(::protos::Ptr(message), id);
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>, typename = hpb::internal::EnableIfHpbClass<T>,
typename = internal::EnableIfMutableProto<T>> typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension( absl::Status SetExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<T, Extension>& id, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
const Extension& value) { const Extension& value) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
return ::protos::internal::SetExtension(internal::GetInternalMsg(message), return ::hpb::internal::SetExtension(hpb::internal::GetInternalMsg(message),
message_arena, id.mini_table_ext(), message_arena, id.mini_table_ext(),
internal::GetInternalMsg(&value)); hpb::internal::GetInternalMsg(&value));
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>, typename = hpb::internal::EnableIfHpbClass<T>,
typename = internal::EnableIfMutableProto<T>> typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension( absl::Status SetExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<T, Extension>& id, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Ptr<Extension> value) { Ptr<Extension> value) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
return ::protos::internal::SetExtension(internal::GetInternalMsg(message), return ::hpb::internal::SetExtension(hpb::internal::GetInternalMsg(message),
message_arena, id.mini_table_ext(), message_arena, id.mini_table_ext(),
internal::GetInternalMsg(value)); hpb::internal::GetInternalMsg(value));
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>, typename = hpb::internal::EnableIfHpbClass<T>,
typename = internal::EnableIfMutableProto<T>> typename = hpb::internal::EnableIfMutableProto<T>>
absl::Status SetExtension( absl::Status SetExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<T, Extension>& id, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Extension&& value) { Extension&& value) {
Extension ext = std::move(value); Extension ext = std::move(value);
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* message_arena = static_cast<upb_Arena*>(message->GetInternalArena());
auto* extension_arena = static_cast<upb_Arena*>(ext.GetInternalArena()); auto* extension_arena = static_cast<upb_Arena*>(ext.GetInternalArena());
return ::protos::internal::MoveExtension( return ::hpb::internal::MoveExtension(hpb::internal::GetInternalMsg(message),
internal::GetInternalMsg(message), message_arena, id.mini_table_ext(), message_arena, id.mini_table_ext(),
internal::GetInternalMsg(&ext), extension_arena); hpb::internal::GetInternalMsg(&ext),
extension_arena);
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
absl::Status SetExtension( absl::Status SetExtension(
T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id, T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
const Extension& value) { const Extension& value) {
return ::protos::SetExtension(::protos::Ptr(message), id, value); return ::hpb::SetExtension(Ptr(message), id, value);
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
absl::Status SetExtension( absl::Status SetExtension(
T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id, T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Extension&& value) { Extension&& value) {
return ::protos::SetExtension(::protos::Ptr(message), id, return ::hpb::SetExtension(Ptr(message), id, std::forward<Extension>(value));
std::forward<Extension>(value));
} }
template <typename T, typename Extension, template <typename T, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
absl::Status SetExtension( absl::Status SetExtension(
T* message, const ::protos::internal::ExtensionIdentifier<T, Extension>& id, T* message, const ::hpb::internal::ExtensionIdentifier<T, Extension>& id,
Ptr<Extension> value) { Ptr<Extension> value) {
return ::protos::SetExtension(::protos::Ptr(message), id, value); return ::hpb::SetExtension(Ptr(message), id, value);
} }
template <typename T, typename Extendee, typename Extension, template <typename T, typename Extendee, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
absl::StatusOr<Ptr<const Extension>> GetExtension( absl::StatusOr<Ptr<const Extension>> GetExtension(
Ptr<T> message, Ptr<T> message,
const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) { const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
// TODO: Fix const correctness issues. // TODO: Fix const correctness issues.
upb_MessageValue value; upb_MessageValue value;
const bool ok = ::protos::internal::GetOrPromoteExtension( const bool ok = ::hpb::internal::GetOrPromoteExtension(
const_cast<upb_Message*>(internal::GetInternalMsg(message)), const_cast<upb_Message*>(::hpb::internal::GetInternalMsg(message)),
id.mini_table_ext(), ::protos::internal::GetArena(message), &value); id.mini_table_ext(), ::hpb::internal::GetArena(message), &value);
if (!ok) { if (!ok) {
return ExtensionNotFoundError( return ExtensionNotFoundError(
upb_MiniTableExtension_Number(id.mini_table_ext())); upb_MiniTableExtension_Number(id.mini_table_ext()));
} }
return Ptr<const Extension>(::protos::internal::CreateMessage<Extension>( return Ptr<const Extension>(::hpb::internal::CreateMessage<Extension>(
(upb_Message*)value.msg_val, ::protos::internal::GetArena(message))); (upb_Message*)value.msg_val, ::hpb::internal::GetArena(message)));
} }
template <typename T, typename Extendee, typename Extension, template <typename T, typename Extendee, typename Extension,
typename = internal::EnableIfHpbClass<T>> typename = hpb::internal::EnableIfHpbClass<T>>
absl::StatusOr<Ptr<const Extension>> GetExtension( absl::StatusOr<Ptr<const Extension>> GetExtension(
const T* message, const T* message,
const ::protos::internal::ExtensionIdentifier<Extendee, Extension>& id) { const ::hpb::internal::ExtensionIdentifier<Extendee, Extension>& id) {
return GetExtension(protos::Ptr(message), id); return GetExtension(Ptr(message), id);
} }
template <typename T>
typename T::Proxy CreateMessage(::hpb::Arena& arena) {
return typename T::Proxy(upb_Message_New(T::minitable(), arena.ptr()),
arena.ptr());
}
template <typename T>
typename T::Proxy CloneMessage(Ptr<T> message, upb_Arena* arena) {
return ::hpb::internal::PrivateAccess::Proxy<T>(
::hpb::internal::DeepClone(::hpb::internal::GetInternalMsg(message),
T::minitable(), arena),
arena);
}
template <typename T>
void DeepCopy(Ptr<const T> source_message, Ptr<T> target_message) {
static_assert(!std::is_const_v<T>);
::hpb::internal::DeepCopy(
hpb::internal::GetInternalMsg(target_message),
hpb::internal::GetInternalMsg(source_message), T::minitable(),
static_cast<upb_Arena*>(target_message->GetInternalArena()));
}
template <typename T>
void DeepCopy(Ptr<const T> source_message, T* target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(source_message, Ptr(target_message));
}
template <typename T>
void DeepCopy(const T* source_message, Ptr<T> target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(Ptr(source_message), target_message);
}
template <typename T>
void DeepCopy(const T* source_message, T* target_message) {
static_assert(!std::is_const_v<T>);
DeepCopy(Ptr(source_message), Ptr(target_message));
}
template <typename T>
void ClearMessage(hpb::internal::PtrOrRaw<T> message) {
auto ptr = Ptr(message);
auto minitable = hpb::internal::GetMiniTable(ptr);
upb_Message_Clear(hpb::internal::GetInternalMsg(ptr), minitable);
}
} // namespace hpb
namespace protos {
using hpb::Arena;
using hpb::ExtensionNotFoundError;
using hpb::MessageAllocationError;
using hpb::MessageDecodeError;
using hpb::MessageEncodeError;
using hpb::Ptr;
using hpb::SourceLocation;
template <typename T> template <typename T>
ABSL_MUST_USE_RESULT bool Parse(Ptr<T> message, absl::string_view bytes) { ABSL_MUST_USE_RESULT bool Parse(Ptr<T> message, absl::string_view bytes) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
upb_Message_Clear(internal::GetInternalMsg(message), upb_Message_Clear(::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message)); ::hpb::internal::GetMiniTable(message));
auto* arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
return upb_Decode(bytes.data(), bytes.size(), return upb_Decode(bytes.data(), bytes.size(),
internal::GetInternalMsg(message), ::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message), ::hpb::internal::GetMiniTable(message),
/* extreg= */ nullptr, /* options= */ 0, /* extreg= */ nullptr, /* options= */ 0,
arena) == kUpb_DecodeStatus_Ok; arena) == kUpb_DecodeStatus_Ok;
} }
@ -493,36 +513,36 @@ ABSL_MUST_USE_RESULT bool Parse(Ptr<T> message, absl::string_view bytes) {
template <typename T> template <typename T>
ABSL_MUST_USE_RESULT bool Parse( ABSL_MUST_USE_RESULT bool Parse(
Ptr<T> message, absl::string_view bytes, Ptr<T> message, absl::string_view bytes,
const ::protos::ExtensionRegistry& extension_registry) { const ::hpb::ExtensionRegistry& extension_registry) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
upb_Message_Clear(internal::GetInternalMsg(message), upb_Message_Clear(::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message)); ::hpb::internal::GetMiniTable(message));
auto* arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
return upb_Decode(bytes.data(), bytes.size(), return upb_Decode(bytes.data(), bytes.size(),
internal::GetInternalMsg(message), ::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message), ::hpb::internal::GetMiniTable(message),
/* extreg= */ /* extreg= */
::protos::internal::GetUpbExtensions(extension_registry), ::hpb::internal::GetUpbExtensions(extension_registry),
/* options= */ 0, arena) == kUpb_DecodeStatus_Ok; /* options= */ 0, arena) == kUpb_DecodeStatus_Ok;
} }
template <typename T> template <typename T>
ABSL_MUST_USE_RESULT bool Parse( ABSL_MUST_USE_RESULT bool Parse(
T* message, absl::string_view bytes, T* message, absl::string_view bytes,
const ::protos::ExtensionRegistry& extension_registry) { const ::hpb::ExtensionRegistry& extension_registry) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
return Parse(protos::Ptr(message, bytes, extension_registry)); return Parse(Ptr(message, bytes, extension_registry));
} }
template <typename T> template <typename T>
ABSL_MUST_USE_RESULT bool Parse(T* message, absl::string_view bytes) { ABSL_MUST_USE_RESULT bool Parse(T* message, absl::string_view bytes) {
static_assert(!std::is_const_v<T>); static_assert(!std::is_const_v<T>);
upb_Message_Clear(internal::GetInternalMsg(message), upb_Message_Clear(::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message)); ::hpb::internal::GetMiniTable(message));
auto* arena = static_cast<upb_Arena*>(message->GetInternalArena()); auto* arena = static_cast<upb_Arena*>(message->GetInternalArena());
return upb_Decode(bytes.data(), bytes.size(), return upb_Decode(bytes.data(), bytes.size(),
internal::GetInternalMsg(message), ::hpb::internal::GetInternalMsg(message),
::protos::internal::GetMiniTable(message), ::hpb::internal::GetMiniTable(message),
/* extreg= */ nullptr, /* options= */ 0, /* extreg= */ nullptr, /* options= */ 0,
arena) == kUpb_DecodeStatus_Ok; arena) == kUpb_DecodeStatus_Ok;
} }
@ -533,7 +553,7 @@ absl::StatusOr<T> Parse(absl::string_view bytes, int options = 0) {
auto* arena = static_cast<upb_Arena*>(message.GetInternalArena()); auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
upb_DecodeStatus status = upb_DecodeStatus status =
upb_Decode(bytes.data(), bytes.size(), message.msg(), upb_Decode(bytes.data(), bytes.size(), message.msg(),
::protos::internal::GetMiniTable(&message), ::hpb::internal::GetMiniTable(&message),
/* extreg= */ nullptr, /* options= */ 0, arena); /* extreg= */ nullptr, /* options= */ 0, arena);
if (status == kUpb_DecodeStatus_Ok) { if (status == kUpb_DecodeStatus_Ok) {
return message; return message;
@ -543,14 +563,14 @@ absl::StatusOr<T> Parse(absl::string_view bytes, int options = 0) {
template <typename T> template <typename T>
absl::StatusOr<T> Parse(absl::string_view bytes, absl::StatusOr<T> Parse(absl::string_view bytes,
const ::protos::ExtensionRegistry& extension_registry, const ::hpb::ExtensionRegistry& extension_registry,
int options = 0) { int options = 0) {
T message; T message;
auto* arena = static_cast<upb_Arena*>(message.GetInternalArena()); auto* arena = static_cast<upb_Arena*>(message.GetInternalArena());
upb_DecodeStatus status = upb_DecodeStatus status =
upb_Decode(bytes.data(), bytes.size(), message.msg(), upb_Decode(bytes.data(), bytes.size(), message.msg(),
::protos::internal::GetMiniTable(&message), ::hpb::internal::GetMiniTable(&message),
::protos::internal::GetUpbExtensions(extension_registry), ::hpb::internal::GetUpbExtensions(extension_registry),
/* options= */ 0, arena); /* options= */ 0, arena);
if (status == kUpb_DecodeStatus_Ok) { if (status == kUpb_DecodeStatus_Ok) {
return message; return message;
@ -561,17 +581,23 @@ absl::StatusOr<T> Parse(absl::string_view bytes,
template <typename T> template <typename T>
absl::StatusOr<absl::string_view> Serialize(const T* message, upb::Arena& arena, absl::StatusOr<absl::string_view> Serialize(const T* message, upb::Arena& arena,
int options = 0) { int options = 0) {
return ::protos::internal::Serialize( return ::hpb::internal::Serialize(::hpb::internal::GetInternalMsg(message),
internal::GetInternalMsg(message), ::hpb::internal::GetMiniTable(message),
::protos::internal::GetMiniTable(message), arena.ptr(), options); arena.ptr(), options);
} }
template <typename T> template <typename T>
absl::StatusOr<absl::string_view> Serialize(Ptr<T> message, upb::Arena& arena, absl::StatusOr<absl::string_view> Serialize(Ptr<T> message, upb::Arena& arena,
int options = 0) { int options = 0) {
return ::protos::internal::Serialize( return ::hpb::internal::Serialize(::hpb::internal::GetInternalMsg(message),
internal::GetInternalMsg(message), ::hpb::internal::GetMiniTable(message),
::protos::internal::GetMiniTable(message), arena.ptr(), options); arena.ptr(), options);
}
template <typename T, typename Extension>
constexpr uint32_t ExtensionNumber(
::hpb::internal::ExtensionIdentifier<T, Extension> id) {
return ::hpb::internal::PrivateAccess::GetExtensionNumber(id);
} }
} // namespace protos } // namespace protos

@ -94,13 +94,13 @@ class RepeatedFieldProxy
: RepeatedFieldProxyBase<T>(arr, arena) {} : RepeatedFieldProxyBase<T>(arr, arena) {}
RepeatedFieldProxy(upb_Array* arr, upb_Arena* arena) RepeatedFieldProxy(upb_Array* arr, upb_Arena* arena)
: RepeatedFieldProxyMutableBase<T>(arr, arena) {} : RepeatedFieldProxyMutableBase<T>(arr, arena) {}
// Constructor used by ::protos::Ptr. // Constructor used by ::hpb::Ptr.
RepeatedFieldProxy(const RepeatedFieldProxy&) = default; RepeatedFieldProxy(const RepeatedFieldProxy&) = default;
// T::CProxy [] operator specialization. // T::CProxy [] operator specialization.
typename T::CProxy operator[](size_t n) const { typename T::CProxy operator[](size_t n) const {
upb_MessageValue message_value = upb_Array_Get(this->arr_, n); upb_MessageValue message_value = upb_Array_Get(this->arr_, n);
return ::protos::internal::CreateMessage<typename std::remove_const_t<T>>( return ::hpb::internal::CreateMessage<typename std::remove_const_t<T>>(
(upb_Message*)message_value.msg_val, this->arena_); (upb_Message*)message_value.msg_val, this->arena_);
} }
@ -109,7 +109,7 @@ class RepeatedFieldProxy
template <int&... DeductionBlocker, bool b = !kIsConst, template <int&... DeductionBlocker, bool b = !kIsConst,
typename = std::enable_if_t<b>> typename = std::enable_if_t<b>>
typename T::Proxy operator[](size_t n) { typename T::Proxy operator[](size_t n) {
return ::protos::internal::CreateMessageProxy<T>(this->GetMessage(n), return ::hpb::internal::CreateMessageProxy<T>(this->GetMessage(n),
this->arena_); this->arena_);
} }
@ -119,8 +119,8 @@ class RepeatedFieldProxy
void push_back(const T& t) { void push_back(const T& t) {
upb_MessageValue message_value; upb_MessageValue message_value;
message_value.msg_val = upb_Message_DeepClone( message_value.msg_val = upb_Message_DeepClone(
PrivateAccess::GetInternalMsg(&t), ::protos::internal::GetMiniTable(&t), ::hpb::internal::PrivateAccess::GetInternalMsg(&t),
this->arena_); ::hpb::internal::GetMiniTable(&t), this->arena_);
upb_Array_Append(this->arr_, message_value, this->arena_); upb_Array_Append(this->arr_, message_value, this->arena_);
} }
@ -129,8 +129,9 @@ class RepeatedFieldProxy
typename = std::enable_if_t<b>> typename = std::enable_if_t<b>>
void push_back(T&& msg) { void push_back(T&& msg) {
upb_MessageValue message_value; upb_MessageValue message_value;
message_value.msg_val = PrivateAccess::GetInternalMsg(&msg); message_value.msg_val =
upb_Arena_Fuse(GetArena(&msg), this->arena_); ::hpb::internal::PrivateAccess::GetInternalMsg(&msg);
upb_Arena_Fuse(::hpb::internal::GetArena(&msg), this->arena_);
upb_Array_Append(this->arr_, message_value, this->arena_); upb_Array_Append(this->arr_, message_value, this->arena_);
T moved_msg = std::move(msg); T moved_msg = std::move(msg);
} }
@ -147,7 +148,7 @@ class RepeatedFieldProxy
reverse_iterator rend() const { return reverse_iterator(begin()); } reverse_iterator rend() const { return reverse_iterator(begin()); }
private: private:
friend class ::protos::Ptr<T>; friend class ::hpb::Ptr<T>;
}; };
// RepeatedField proxy for repeated strings. // RepeatedField proxy for repeated strings.
@ -175,7 +176,7 @@ class RepeatedFieldStringProxy
// Mutable constructor. // Mutable constructor.
RepeatedFieldStringProxy(upb_Array* arr, upb_Arena* arena) RepeatedFieldStringProxy(upb_Array* arr, upb_Arena* arena)
: RepeatedFieldProxyMutableBase<T>(arr, arena) {} : RepeatedFieldProxyMutableBase<T>(arr, arena) {}
// Constructor used by ::protos::Ptr. // Constructor used by ::hpb::Ptr.
RepeatedFieldStringProxy(const RepeatedFieldStringProxy&) = default; RepeatedFieldStringProxy(const RepeatedFieldStringProxy&) = default;
reference operator[](size_t n) const { return begin()[n]; } reference operator[](size_t n) const { return begin()[n]; }
@ -222,7 +223,7 @@ class RepeatedFieldScalarProxy
: RepeatedFieldProxyBase<T>(arr, arena) {} : RepeatedFieldProxyBase<T>(arr, arena) {}
RepeatedFieldScalarProxy(upb_Array* arr, upb_Arena* arena) RepeatedFieldScalarProxy(upb_Array* arr, upb_Arena* arena)
: RepeatedFieldProxyMutableBase<T>(arr, arena) {} : RepeatedFieldProxyMutableBase<T>(arr, arena) {}
// Constructor used by ::protos::Ptr. // Constructor used by ::hpb::Ptr.
RepeatedFieldScalarProxy(const RepeatedFieldScalarProxy&) = default; RepeatedFieldScalarProxy(const RepeatedFieldScalarProxy&) = default;
T operator[](size_t n) const { T operator[](size_t n) const {
@ -285,10 +286,10 @@ class RepeatedField {
// We would like to reference T::CProxy. Validate forwarding header design. // We would like to reference T::CProxy. Validate forwarding header design.
using ValueProxy = std::conditional_t< using ValueProxy = std::conditional_t<
kIsScalar, T, kIsScalar, T,
std::conditional_t<kIsString, absl::string_view, ::protos::Ptr<T>>>; std::conditional_t<kIsString, absl::string_view, ::hpb::Ptr<T>>>;
using ValueCProxy = std::conditional_t< using ValueCProxy = std::conditional_t<
kIsScalar, const T, kIsScalar, const T,
std::conditional_t<kIsString, absl::string_view, ::protos::Ptr<const T>>>; std::conditional_t<kIsString, absl::string_view, ::hpb::Ptr<const T>>>;
using Access = std::conditional_t< using Access = std::conditional_t<
kIsScalar, internal::RepeatedFieldScalarProxy<T>, kIsScalar, internal::RepeatedFieldScalarProxy<T>,
std::conditional_t<kIsString, internal::RepeatedFieldStringProxy<T>, std::conditional_t<kIsString, internal::RepeatedFieldStringProxy<T>,

@ -354,10 +354,10 @@ struct MessageIteratorPolicy {
void AddOffset(ptrdiff_t offset) { arr += offset; } void AddOffset(ptrdiff_t offset) { arr += offset; }
auto Get() const { auto Get() const {
if constexpr (std::is_const_v<T>) { if constexpr (std::is_const_v<T>) {
return ::protos::internal::CreateMessage< return ::hpb::internal::CreateMessage<typename std::remove_const_t<T>>(
typename std::remove_const_t<T>>(*arr, arena); *arr, arena);
} else { } else {
return ::protos::internal::CreateMessageProxy<T>(*arr, arena); return ::hpb::internal::CreateMessageProxy<T>(*arr, arena);
} }
} }
auto Index() const { return arr; } auto Index() const { return arr; }

@ -11,7 +11,7 @@ load(
) )
# begin:google_only # begin:google_only
# package(default_applicable_licenses = ["//upb:license"]) # package(default_applicable_licenses = ["//src/google/protobuf:license"])
# end:google_only # end:google_only
licenses(["notice"]) licenses(["notice"])

@ -222,7 +222,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
output( output(
R"cc( R"cc(
$1 $0::$2() const { $1 $0::$2() const {
return ::protos::UpbStrToStringView($3_$4(msg_)); return ::hpb::UpbStrToStringView($3_$4(msg_));
} }
)cc", )cc",
class_name, CppConstType(field), resolved_field_name, class_name, CppConstType(field), resolved_field_name,
@ -231,7 +231,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
output( output(
R"cc( R"cc(
void $0::set_$2($1 value) { void $0::set_$2($1 value) {
$4_set_$3(msg_, ::protos::UpbStrFromStringView(value, $5)); $4_set_$3(msg_, ::hpb::UpbStrFromStringView(value, $5));
} }
)cc", )cc",
class_name, CppConstType(field), resolved_field_name, class_name, CppConstType(field), resolved_field_name,
@ -244,7 +244,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
if (!has_$2()) { if (!has_$2()) {
return $4::default_instance(); return $4::default_instance();
} }
return ::protos::internal::CreateMessage<$4>( return ::hpb::internal::CreateMessage<$4>(
(upb_Message*)($3_$5(msg_)), arena_); (upb_Message*)($3_$5(msg_)), arena_);
} }
)cc", )cc",
@ -256,7 +256,7 @@ void WriteAccessorsInSource(const protobuf::Descriptor* desc, Output& output) {
output( output(
R"cc( R"cc(
$1 $0::mutable_$2() { $1 $0::mutable_$2() {
return ::protos::internal::CreateMessageProxy<$4>( return ::hpb::internal::CreateMessageProxy<$4>(
(upb_Message*)($3_mutable_$5(msg_, $6)), $6); (upb_Message*)($3_mutable_$5(msg_, $6)), $6);
} }
)cc", )cc",
@ -295,7 +295,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
R"cc( R"cc(
bool $0::set_$1($2 key, $3 value) { bool $0::set_$1($2 key, $3 value) {
upb_Message* clone = upb_Message_DeepClone( upb_Message* clone = upb_Message_DeepClone(
::protos::internal::PrivateAccess::GetInternalMsg(value), &$9, ::hpb::internal::PrivateAccess::GetInternalMsg(value), &$9,
arena_); arena_);
$6return $4_$8_set(msg_, $7, ($5*)clone, arena_); $6return $4_$8_set(msg_, $7, ($5*)clone, arena_);
} }
@ -309,7 +309,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
R"cc( R"cc(
bool $0::set_$1($2 key, $3 value) { bool $0::set_$1($2 key, $3 value) {
upb_Message* clone = upb_Message_DeepClone( upb_Message* clone = upb_Message_DeepClone(
::protos::internal::PrivateAccess::GetInternalMsg(value), &$9, ::hpb::internal::PrivateAccess::GetInternalMsg(value), &$9,
arena_); arena_);
$6return $4_$8_set(msg_, $7, ($5*)clone, arena_); $6return $4_$8_set(msg_, $7, ($5*)clone, arena_);
} }
@ -325,7 +325,7 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
$5* msg_value; $5* msg_value;
$7bool success = $4_$9_get(msg_, $8, &msg_value); $7bool success = $4_$9_get(msg_, $8, &msg_value);
if (success) { if (success) {
return ::protos::internal::CreateMessage<$6>(UPB_UPCAST(msg_value), arena_); return ::hpb::internal::CreateMessage<$6>(UPB_UPCAST(msg_value), arena_);
} }
return absl::NotFoundError(""); return absl::NotFoundError("");
} }
@ -347,9 +347,8 @@ void WriteMapAccessorDefinitions(const protobuf::Descriptor* message,
output( output(
R"cc( R"cc(
bool $0::set_$1($2 key, $3 value) { bool $0::set_$1($2 key, $3 value) {
$5return $4_$7_set(msg_, $6, $5return $4_$7_set(
::protos::UpbStrFromStringView(value, arena_), msg_, $6, ::hpb::UpbStrFromStringView(value, arena_), arena_);
arena_);
} }
)cc", )cc",
class_name, resolved_field_name, CppConstType(key), CppConstType(val), class_name, resolved_field_name, CppConstType(key), CppConstType(val),

@ -38,13 +38,13 @@ void WriteExtensionIdentifierHeader(const protobuf::FieldDescriptor* ext,
if (ext->extension_scope()) { if (ext->extension_scope()) {
output( output(
R"cc( R"cc(
static const ::protos::internal::ExtensionIdentifier<$0, $1> $2; static const ::hpb::internal::ExtensionIdentifier<$0, $1> $2;
)cc", )cc",
ContainingTypeName(ext), CppTypeParameterName(ext), ext->name()); ContainingTypeName(ext), CppTypeParameterName(ext), ext->name());
} else { } else {
output( output(
R"cc( R"cc(
extern const ::protos::internal::ExtensionIdentifier<$0, $1> $2; extern const ::hpb::internal::ExtensionIdentifier<$0, $1> $2;
)cc", )cc",
ContainingTypeName(ext), CppTypeParameterName(ext), ext->name()); ContainingTypeName(ext), CppTypeParameterName(ext), ext->name());
} }

@ -113,7 +113,7 @@ void WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor,
friend class $2; friend class $2;
friend class $0Proxy; friend class $0Proxy;
friend class $0CProxy; friend class $0CProxy;
friend struct ::protos::internal::PrivateAccess; friend struct ::hpb::internal::PrivateAccess;
$1* msg_; $1* msg_;
upb_Arena* arena_; upb_Arena* arena_;
)cc", )cc",
@ -242,18 +242,17 @@ void WriteModelPublicDeclaration(
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
upb_Arena_Fuse(arena_, arena); upb_Arena_Fuse(arena_, arena);
} }
::protos::Arena owned_arena_; ::hpb::Arena owned_arena_;
friend struct ::protos::internal::PrivateAccess; friend struct ::hpb::internal::PrivateAccess;
friend Proxy; friend Proxy;
friend CProxy; friend CProxy;
friend absl::StatusOr<$2>(::protos::Parse<$2>(absl::string_view bytes, friend absl::StatusOr<$2>(::protos::Parse<$2>(absl::string_view bytes,
int options)); int options));
friend absl::StatusOr<$2>(::protos::Parse<$2>( friend absl::StatusOr<$2>(::protos::Parse<$2>(
absl::string_view bytes, absl::string_view bytes,
const ::protos::ExtensionRegistry& extension_registry, const ::hpb::ExtensionRegistry& extension_registry, int options));
int options)); friend upb_Arena* ::hpb::internal::GetArena<$0>($0* message);
friend upb_Arena* ::protos::internal::GetArena<$0>($0* message); friend upb_Arena* ::hpb::internal::GetArena<$0>(::hpb::Ptr<$0> message);
friend upb_Arena* ::protos::internal::GetArena<$0>(::protos::Ptr<$0> message);
friend $0(::hpb::internal::MoveMessage<$0>(upb_Message* msg, upb_Arena* arena)); friend $0(::hpb::internal::MoveMessage<$0>(upb_Message* msg, upb_Arena* arena));
)cc", )cc",
ClassName(descriptor), MessageName(descriptor), ClassName(descriptor), MessageName(descriptor),
@ -298,22 +297,22 @@ void WriteModelProxyDeclaration(const protobuf::Descriptor* descriptor,
$0Proxy(upb_Message* msg, upb_Arena* arena) $0Proxy(upb_Message* msg, upb_Arena* arena)
: internal::$0Access(($1*)msg, arena) {} : internal::$0Access(($1*)msg, arena) {}
friend $0::Proxy(::protos::CreateMessage<$0>(::protos::Arena& arena)); friend $0::Proxy(::hpb::CreateMessage<$0>(::hpb::Arena& arena));
friend $0::Proxy(::protos::internal::CreateMessageProxy<$0>( friend $0::Proxy(::hpb::internal::CreateMessageProxy<$0>(upb_Message*,
upb_Message*, upb_Arena*)); upb_Arena*));
friend struct ::protos::internal::PrivateAccess; friend struct ::hpb::internal::PrivateAccess;
friend class RepeatedFieldProxy; friend class RepeatedFieldProxy;
friend class $0CProxy; friend class $0CProxy;
friend class $0Access; friend class $0Access;
friend class ::protos::Ptr<$0>; friend class ::hpb::Ptr<$0>;
friend class ::protos::Ptr<const $0>; friend class ::hpb::Ptr<const $0>;
static const upb_MiniTable* minitable() { return $0::minitable(); } static const upb_MiniTable* minitable() { return $0::minitable(); }
friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>( friend const upb_MiniTable* ::hpb::internal::GetMiniTable<$0Proxy>(
const $0Proxy* message); const $0Proxy* message);
friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0Proxy>( friend const upb_MiniTable* ::hpb::internal::GetMiniTable<$0Proxy>(
::protos::Ptr<$0Proxy> message); ::hpb::Ptr<$0Proxy> message);
friend upb_Arena* ::protos::internal::GetArena<$2>($2* message); friend upb_Arena* ::hpb::internal::GetArena<$2>($2* message);
friend upb_Arena* ::protos::internal::GetArena<$2>(::protos::Ptr<$2> message); friend upb_Arena* ::hpb::internal::GetArena<$2>(::hpb::Ptr<$2> message);
static void Rebind($0Proxy& lhs, const $0Proxy& rhs) { static void Rebind($0Proxy& lhs, const $0Proxy& rhs) {
lhs.msg_ = rhs.msg_; lhs.msg_ = rhs.msg_;
lhs.arena_ = rhs.arena_; lhs.arena_ = rhs.arena_;
@ -334,7 +333,7 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
public: public:
$0CProxy() = delete; $0CProxy() = delete;
$0CProxy(const $0* m) $0CProxy(const $0* m)
: internal::$0Access(m->msg_, ::protos::internal::GetArena(m)) {} : internal::$0Access(m->msg_, ::hpb::internal::GetArena(m)) {}
$0CProxy($0Proxy m); $0CProxy($0Proxy m);
using $0Access::GetInternalArena; using $0Access::GetInternalArena;
)cc", )cc",
@ -352,15 +351,15 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
$0CProxy(const upb_Message* msg, upb_Arena* arena) $0CProxy(const upb_Message* msg, upb_Arena* arena)
: internal::$0Access(($1*)msg, arena){}; : internal::$0Access(($1*)msg, arena){};
friend struct ::protos::internal::PrivateAccess; friend struct ::hpb::internal::PrivateAccess;
friend class RepeatedFieldProxy; friend class RepeatedFieldProxy;
friend class ::protos::Ptr<$0>; friend class ::hpb::Ptr<$0>;
friend class ::protos::Ptr<const $0>; friend class ::hpb::Ptr<const $0>;
static const upb_MiniTable* minitable() { return $0::minitable(); } static const upb_MiniTable* minitable() { return $0::minitable(); }
friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>( friend const upb_MiniTable* ::hpb::internal::GetMiniTable<$0CProxy>(
const $0CProxy* message); const $0CProxy* message);
friend const upb_MiniTable* ::protos::internal::GetMiniTable<$0CProxy>( friend const upb_MiniTable* ::hpb::internal::GetMiniTable<$0CProxy>(
::protos::Ptr<$0CProxy> message); ::hpb::Ptr<$0CProxy> message);
static void Rebind($0CProxy& lhs, const $0CProxy& rhs) { static void Rebind($0CProxy& lhs, const $0CProxy& rhs) {
lhs.msg_ = rhs.msg_; lhs.msg_ = rhs.msg_;
@ -374,7 +373,7 @@ void WriteModelCProxyDeclaration(const protobuf::Descriptor* descriptor,
void WriteDefaultInstanceHeader(const protobuf::Descriptor* message, void WriteDefaultInstanceHeader(const protobuf::Descriptor* message,
Output& output) { Output& output) {
output(" static ::protos::Ptr<const $0> default_instance();\n", output(" static ::hpb::Ptr<const $0> default_instance();\n",
ClassName(message)); ClassName(message));
} }
@ -393,27 +392,27 @@ void WriteMessageImplementation(
} }
$0::$0(const $0& from) : $0Access() { $0::$0(const $0& from) : $0Access() {
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
msg_ = ($1*)::protos::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); msg_ = ($1*)::hpb::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_);
} }
$0::$0(const CProxy& from) : $0Access() { $0::$0(const CProxy& from) : $0Access() {
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
msg_ = ($1*)::protos::internal::DeepClone( msg_ = ($1*)::hpb::internal::DeepClone(
::protos::internal::GetInternalMsg(&from), &$2, arena_); ::hpb::internal::GetInternalMsg(&from), &$2, arena_);
} }
$0::$0(const Proxy& from) : $0(static_cast<const CProxy&>(from)) {} $0::$0(const Proxy& from) : $0(static_cast<const CProxy&>(from)) {}
internal::$0CProxy::$0CProxy($0Proxy m) : $0Access() { internal::$0CProxy::$0CProxy($0Proxy m) : $0Access() {
arena_ = m.arena_; arena_ = m.arena_;
msg_ = ($1*)::protos::internal::GetInternalMsg(&m); msg_ = ($1*)::hpb::internal::GetInternalMsg(&m);
} }
$0& $0::operator=(const $3& from) { $0& $0::operator=(const $3& from) {
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
msg_ = ($1*)::protos::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_); msg_ = ($1*)::hpb::internal::DeepClone(UPB_UPCAST(from.msg_), &$2, arena_);
return *this; return *this;
} }
$0& $0::operator=(const CProxy& from) { $0& $0::operator=(const CProxy& from) {
arena_ = owned_arena_.ptr(); arena_ = owned_arena_.ptr();
msg_ = ($1*)::protos::internal::DeepClone( msg_ = ($1*)::hpb::internal::DeepClone(
::protos::internal::GetInternalMsg(&from), &$2, arena_); ::hpb::internal::GetInternalMsg(&from), &$2, arena_);
return *this; return *this;
} }
)cc", )cc",
@ -450,8 +449,8 @@ void WriteMessageImplementation(
output( output(
R"cc( R"cc(
::protos::Ptr<const $0> $0::default_instance() { ::hpb::Ptr<const $0> $0::default_instance() {
return ::protos::internal::CreateMessage<$0>( return ::hpb::internal::CreateMessage<$0>(
(upb_Message *)_$0_default_instance_.msg, (upb_Message *)_$0_default_instance_.msg,
_$0_default_instance_.arena); _$0_default_instance_.arena);
} }

@ -87,7 +87,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
R"cc( R"cc(
$1 $2(size_t index) const; $1 $2(size_t index) const;
const ::protos::RepeatedField<const $4>::CProxy $2() const; const ::protos::RepeatedField<const $4>::CProxy $2() const;
::protos::Ptr<::protos::RepeatedField<$4>> mutable_$2(); ::hpb::Ptr<::protos::RepeatedField<$4>> mutable_$2();
absl::StatusOr<$0> add_$2(); absl::StatusOr<$0> add_$2();
$0 mutable_$2(size_t index) const; $0 mutable_$2(size_t index) const;
)cc", )cc",
@ -102,7 +102,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
R"cc( R"cc(
$0 $1(size_t index) const; $0 $1(size_t index) const;
const ::protos::RepeatedField<$0>::CProxy $1() const; const ::protos::RepeatedField<$0>::CProxy $1() const;
::protos::Ptr<::protos::RepeatedField<$0>> mutable_$1(); ::hpb::Ptr<::protos::RepeatedField<$0>> mutable_$1();
bool add_$1($0 val); bool add_$1($0 val);
void set_$1(size_t index, $0 val); void set_$1(size_t index, $0 val);
bool resize_$1(size_t len); bool resize_$1(size_t len);
@ -113,7 +113,7 @@ void WriteRepeatedFieldsInMessageHeader(const protobuf::Descriptor* desc,
R"cc( R"cc(
$0 $1(size_t index) const; $0 $1(size_t index) const;
const ::protos::RepeatedField<$0>::CProxy $1() const; const ::protos::RepeatedField<$0>::CProxy $1() const;
::protos::Ptr<::protos::RepeatedField<$0>> mutable_$1(); ::hpb::Ptr<::protos::RepeatedField<$0>> mutable_$1();
bool add_$1($0 val); bool add_$1($0 val);
void set_$1(size_t index, $0 val); void set_$1(size_t index, $0 val);
bool resize_$1(size_t len); bool resize_$1(size_t len);
@ -135,7 +135,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
size_t len; size_t len;
auto* ptr = $3_$5(msg_, &len); auto* ptr = $3_$5(msg_, &len);
assert(index < len); assert(index < len);
return ::protos::internal::CreateMessage<$4>( return ::hpb::internal::CreateMessage<$4>(
(upb_Message*)*(ptr + index), arena_); (upb_Message*)*(ptr + index), arena_);
} }
)cc", )cc",
@ -149,7 +149,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
if (!new_msg) { if (!new_msg) {
return ::protos::MessageAllocationError(); return ::protos::MessageAllocationError();
} }
return ::protos::internal::CreateMessageProxy<$4>((upb_Message*)new_msg, $5); return ::hpb::internal::CreateMessageProxy<$4>((upb_Message*)new_msg, $5);
} }
)cc", )cc",
class_name, MessagePtrConstType(field, /* const */ false), class_name, MessagePtrConstType(field, /* const */ false),
@ -162,7 +162,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
size_t len; size_t len;
auto* ptr = $3_$6(msg_, &len); auto* ptr = $3_$6(msg_, &len);
assert(index < len); assert(index < len);
return ::protos::internal::CreateMessageProxy<$4>( return ::hpb::internal::CreateMessageProxy<$4>(
(upb_Message*)*(ptr + index), $5); (upb_Message*)*(ptr + index), $5);
} }
)cc", )cc",
@ -177,7 +177,7 @@ void WriteRepeatedMessageAccessor(const protobuf::Descriptor* message,
const upb_Array* arr = _$3_$4_$5(msg_, &size); const upb_Array* arr = _$3_$4_$5(msg_, &size);
return ::protos::RepeatedField<const $1>::CProxy(arr, arena_); return ::protos::RepeatedField<const $1>::CProxy(arr, arena_);
}; };
::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { ::hpb::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() {
size_t size; size_t size;
upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
return ::protos::RepeatedField<$1>::Proxy(arr, arena_); return ::protos::RepeatedField<$1>::Proxy(arr, arena_);
@ -205,7 +205,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
size_t len; size_t len;
auto* ptr = $3_mutable_$4(msg_, &len); auto* ptr = $3_mutable_$4(msg_, &len);
assert(index < len); assert(index < len);
return ::protos::UpbStrToStringView(*(ptr + index)); return ::hpb::UpbStrToStringView(*(ptr + index));
} }
)cc", )cc",
class_name, CppConstType(field), resolved_field_name, class_name, CppConstType(field), resolved_field_name,
@ -220,7 +220,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
output( output(
R"cc( R"cc(
bool $0::add_$2($1 val) { bool $0::add_$2($1 val) {
return $3_add_$4(msg_, ::protos::UpbStrFromStringView(val, arena_), arena_); return $3_add_$4(msg_, ::hpb::UpbStrFromStringView(val, arena_), arena_);
} }
)cc", )cc",
class_name, CppConstType(field), resolved_field_name, class_name, CppConstType(field), resolved_field_name,
@ -231,7 +231,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
size_t len; size_t len;
auto* ptr = $3_mutable_$4(msg_, &len); auto* ptr = $3_mutable_$4(msg_, &len);
assert(index < len); assert(index < len);
*(ptr + index) = ::protos::UpbStrFromStringView(val, arena_); *(ptr + index) = ::hpb::UpbStrFromStringView(val, arena_);
} }
)cc", )cc",
class_name, CppConstType(field), resolved_field_name, class_name, CppConstType(field), resolved_field_name,
@ -243,7 +243,7 @@ void WriteRepeatedStringAccessor(const protobuf::Descriptor* message,
const upb_Array* arr = _$3_$4_$5(msg_, &size); const upb_Array* arr = _$3_$4_$5(msg_, &size);
return ::protos::RepeatedField<$1>::CProxy(arr, arena_); return ::protos::RepeatedField<$1>::CProxy(arr, arena_);
}; };
::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { ::hpb::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() {
size_t size; size_t size;
upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
return ::protos::RepeatedField<$1>::Proxy(arr, arena_); return ::protos::RepeatedField<$1>::Proxy(arr, arena_);
@ -307,7 +307,7 @@ void WriteRepeatedScalarAccessor(const protobuf::Descriptor* message,
const upb_Array* arr = _$3_$4_$5(msg_, &size); const upb_Array* arr = _$3_$4_$5(msg_, &size);
return ::protos::RepeatedField<$1>::CProxy(arr, arena_); return ::protos::RepeatedField<$1>::CProxy(arr, arena_);
}; };
::protos::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() { ::hpb::Ptr<::protos::RepeatedField<$1>> $0::mutable_$2() {
size_t size; size_t size;
upb_Array* arr = _$3_$4_$6(msg_, &size, arena_); upb_Array* arr = _$3_$4_$6(msg_, &size, arena_);
return ::protos::RepeatedField<$1>::Proxy(arr, arena_); return ::protos::RepeatedField<$1>::Proxy(arr, arena_);

@ -17,6 +17,7 @@ namespace protobuf = ::proto2;
namespace { namespace {
// TODO: b/346865271 append ::hpb instead of ::protos after namespace swap
std::string NamespaceFromPackageName(absl::string_view package_name) { std::string NamespaceFromPackageName(absl::string_view package_name) {
return absl::StrCat(absl::StrReplaceAll(package_name, {{".", "::"}}), return absl::StrCat(absl::StrReplaceAll(package_name, {{".", "::"}}),
"::protos"); "::protos");
@ -82,7 +83,7 @@ std::string ClassName(const protobuf::Descriptor* descriptor) {
const protobuf::Descriptor* parent = descriptor->containing_type(); const protobuf::Descriptor* parent = descriptor->containing_type();
std::string res; std::string res;
// Classes in global namespace without package names are prefixed // Classes in global namespace without package names are prefixed
// by protos_ to avoid collision with C compiler structs defined in // by hpb_ to avoid collision with C compiler structs defined in
// proto.upb.h. // proto.upb.h.
if ((parent && parent->file()->package().empty()) || if ((parent && parent->file()->package().empty()) ||
descriptor->file()->package().empty()) { descriptor->file()->package().empty()) {
@ -155,7 +156,7 @@ std::string MessagePtrConstType(const protobuf::FieldDescriptor* field,
bool is_const) { bool is_const) {
ABSL_DCHECK(field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE); ABSL_DCHECK(field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE);
std::string maybe_const = is_const ? "const " : ""; std::string maybe_const = is_const ? "const " : "";
return "::protos::Ptr<" + maybe_const + return "::hpb::Ptr<" + maybe_const +
QualifiedClassName(field->message_type()) + ">"; QualifiedClassName(field->message_type()) + ">";
} }

@ -156,8 +156,9 @@
# "@com_google_absl//absl/strings", # "@com_google_absl//absl/strings",
# "//hpb:requires", # "//hpb:requires",
# "//hpb", # "//hpb",
# "//upb:mem",
# "//hpb:repeated_field", # "//hpb:repeated_field",
# "//protos",
# "//upb:mem",
# ], # ],
# ) # )
# end:google_only # end:google_only

@ -20,8 +20,10 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h" #include "google/protobuf/compiler/hpb/tests/child_model.upb.proto.h"
#include "google/protobuf/compiler/hpb/tests/no_package.upb.proto.h" #include "google/protobuf/compiler/hpb/tests/no_package.upb.proto.h"
#include "google/protobuf/compiler/hpb/tests/test_extension.upb.proto.h"
#include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h" #include "google/protobuf/compiler/hpb/tests/test_model.upb.proto.h"
#include "google/protobuf/hpb/hpb.h" #include "google/protobuf/hpb/hpb.h"
#include "google/protobuf/hpb/repeated_field.h"
#include "google/protobuf/hpb/requires.h" #include "google/protobuf/hpb/requires.h"
#include "upb/mem/arena.h" #include "upb/mem/arena.h"
#include "upb/mem/arena.hpp" #include "upb/mem/arena.hpp"
@ -66,13 +68,13 @@ TEST(CppGeneratedCode, MessageEnumValue) {
TEST(CppGeneratedCode, ArenaConstructor) { TEST(CppGeneratedCode, ArenaConstructor) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(false, testModel.has_b1()); EXPECT_EQ(false, testModel.has_b1());
} }
TEST(CppGeneratedCode, Booleans) { TEST(CppGeneratedCode, Booleans) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_FALSE(testModel.b1()); EXPECT_FALSE(testModel.b1());
testModel.set_b1(true); testModel.set_b1(true);
EXPECT_TRUE(testModel.b1()); EXPECT_TRUE(testModel.b1());
@ -86,7 +88,7 @@ TEST(CppGeneratedCode, Booleans) {
TEST(CppGeneratedCode, ScalarInt32) { TEST(CppGeneratedCode, ScalarInt32) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Test int32 defaults. // Test int32 defaults.
EXPECT_EQ(testModel.value(), 0); EXPECT_EQ(testModel.value(), 0);
EXPECT_FALSE(testModel.has_value()); EXPECT_FALSE(testModel.has_value());
@ -129,7 +131,7 @@ TEST(CppGeneratedCode, Strings) {
TEST(CppGeneratedCode, ScalarUInt32) { TEST(CppGeneratedCode, ScalarUInt32) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Test defaults. // Test defaults.
EXPECT_EQ(testModel.optional_uint32(), 0); EXPECT_EQ(testModel.optional_uint32(), 0);
EXPECT_FALSE(testModel.has_optional_uint32()); EXPECT_FALSE(testModel.has_optional_uint32());
@ -149,16 +151,16 @@ TEST(CppGeneratedCode, ScalarUInt32) {
TEST(CppGeneratedCode, ScalarInt64) { TEST(CppGeneratedCode, ScalarInt64) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Test defaults. // Test defaults.
EXPECT_EQ(testModel.optional_int64(), 0); EXPECT_EQ(testModel.optional_int64(), 0);
EXPECT_FALSE(testModel.has_optional_int64()); EXPECT_FALSE(testModel.has_optional_int64());
// Set value. // Set value.
testModel.set_optional_int64(0xFF00CCDDA0001000); testModel.set_optional_int64(static_cast<int64_t>(0xFF00CCDDA0001000));
EXPECT_TRUE(testModel.has_optional_int64()); EXPECT_TRUE(testModel.has_optional_int64());
EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000);
// Change value. // Change value.
testModel.set_optional_int64(0xFF00CCDD70002000); testModel.set_optional_int64(static_cast<int64_t>(0xFF00CCDD70002000));
EXPECT_TRUE(testModel.has_optional_int64()); EXPECT_TRUE(testModel.has_optional_int64());
EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDD70002000); EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDD70002000);
// Clear value. // Clear value.
@ -166,14 +168,14 @@ TEST(CppGeneratedCode, ScalarInt64) {
EXPECT_FALSE(testModel.has_optional_int64()); EXPECT_FALSE(testModel.has_optional_int64());
EXPECT_EQ(testModel.optional_int64(), 0); EXPECT_EQ(testModel.optional_int64(), 0);
// Set after clear. // Set after clear.
testModel.set_optional_int64(0xFF00CCDDA0001000); testModel.set_optional_int64(static_cast<int64_t>(0xFF00CCDDA0001000));
EXPECT_TRUE(testModel.has_optional_int64()); EXPECT_TRUE(testModel.has_optional_int64());
EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000); EXPECT_EQ(testModel.optional_int64(), 0xFF00CCDDA0001000);
} }
TEST(CppGeneratedCode, ScalarFloat) { TEST(CppGeneratedCode, ScalarFloat) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Test defaults. // Test defaults.
EXPECT_EQ(testModel.optional_float(), 0.0f); EXPECT_EQ(testModel.optional_float(), 0.0f);
EXPECT_FALSE(testModel.has_optional_float()); EXPECT_FALSE(testModel.has_optional_float());
@ -201,7 +203,7 @@ TEST(CppGeneratedCode, ScalarFloat) {
TEST(CppGeneratedCode, ScalarDouble) { TEST(CppGeneratedCode, ScalarDouble) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Test defaults. // Test defaults.
EXPECT_EQ(testModel.optional_double(), 0.0); EXPECT_EQ(testModel.optional_double(), 0.0);
EXPECT_FALSE(testModel.has_optional_double()); EXPECT_FALSE(testModel.has_optional_double());
@ -225,7 +227,7 @@ TEST(CppGeneratedCode, ScalarDouble) {
TEST(CppGeneratedCode, Enums) { TEST(CppGeneratedCode, Enums) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
// Check enum default value. // Check enum default value.
EXPECT_EQ(TestModel_Category_IMAGES, 5); EXPECT_EQ(TestModel_Category_IMAGES, 5);
@ -253,7 +255,7 @@ TEST(CppGeneratedCode, Enums) {
TEST(CppGeneratedCode, FieldWithDefaultValue) { TEST(CppGeneratedCode, FieldWithDefaultValue) {
::hpb::Arena arena; ::hpb::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena); auto testModel = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_FALSE(testModel.has_int_value_with_default()); EXPECT_FALSE(testModel.has_int_value_with_default());
EXPECT_EQ(testModel.int_value_with_default(), 65); EXPECT_EQ(testModel.int_value_with_default(), 65);
@ -268,7 +270,7 @@ TEST(CppGeneratedCode, FieldWithDefaultValue) {
TEST(CppGeneratedCode, OneOfFields) { TEST(CppGeneratedCode, OneOfFields) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_FALSE(test_model.has_oneof_member1()); EXPECT_FALSE(test_model.has_oneof_member1());
EXPECT_FALSE(test_model.has_oneof_member2()); EXPECT_FALSE(test_model.has_oneof_member2());
@ -296,7 +298,7 @@ TEST(CppGeneratedCode, OneOfFields) {
TEST(CppGeneratedCode, Messages) { TEST(CppGeneratedCode, Messages) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(false, test_model.has_child_model_1()); EXPECT_EQ(false, test_model.has_child_model_1());
auto child_model = test_model.child_model_1(); auto child_model = test_model.child_model_1();
EXPECT_EQ(false, child_model->has_child_b1()); EXPECT_EQ(false, child_model->has_child_b1());
@ -320,7 +322,7 @@ TEST(CppGeneratedCode, Messages) {
TEST(CppGeneratedCode, NestedMessages) { TEST(CppGeneratedCode, NestedMessages) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
auto nested_child = test_model.nested_child_1(); auto nested_child = test_model.nested_child_1();
EXPECT_EQ(0, nested_child->nested_child_name().size()); EXPECT_EQ(0, nested_child->nested_child_name().size());
auto mutable_nested_child = test_model.mutable_nested_child_1(); auto mutable_nested_child = test_model.mutable_nested_child_1();
@ -331,7 +333,7 @@ TEST(CppGeneratedCode, NestedMessages) {
TEST(CppGeneratedCode, RepeatedMessages) { TEST(CppGeneratedCode, RepeatedMessages) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.child_models_size()); EXPECT_EQ(0, test_model.child_models_size());
// Should be able to clear repeated field when empty. // Should be able to clear repeated field when empty.
test_model.mutable_child_models()->clear(); test_model.mutable_child_models()->clear();
@ -360,7 +362,7 @@ TEST(CppGeneratedCode, RepeatedMessages) {
TEST(CppGeneratedCode, RepeatedScalar) { TEST(CppGeneratedCode, RepeatedScalar) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.value_array_size()); EXPECT_EQ(0, test_model.value_array_size());
// Should be able to clear repeated field when empty. // Should be able to clear repeated field when empty.
test_model.mutable_value_array()->clear(); test_model.mutable_value_array()->clear();
@ -381,7 +383,7 @@ TEST(CppGeneratedCode, RepeatedScalar) {
TEST(CppGeneratedCode, RepeatedFieldClear) { TEST(CppGeneratedCode, RepeatedFieldClear) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
test_model.mutable_value_array()->push_back(5); test_model.mutable_value_array()->push_back(5);
test_model.mutable_value_array()->push_back(16); test_model.mutable_value_array()->push_back(16);
test_model.mutable_value_array()->push_back(27); test_model.mutable_value_array()->push_back(27);
@ -392,7 +394,7 @@ TEST(CppGeneratedCode, RepeatedFieldClear) {
TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) { TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.value_array().size()); EXPECT_EQ(0, test_model.value_array().size());
EXPECT_EQ(0, test_model.mutable_value_array()->size()); EXPECT_EQ(0, test_model.mutable_value_array()->size());
@ -425,7 +427,7 @@ TEST(CppGeneratedCode, RepeatedFieldProxyForScalars) {
TEST(CppGeneratedCode, RepeatedScalarIterator) { TEST(CppGeneratedCode, RepeatedScalarIterator) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
test_model.mutable_value_array()->push_back(5); test_model.mutable_value_array()->push_back(5);
test_model.mutable_value_array()->push_back(16); test_model.mutable_value_array()->push_back(16);
test_model.mutable_value_array()->push_back(27); test_model.mutable_value_array()->push_back(27);
@ -492,7 +494,7 @@ TEST(CppGeneratedCode, RepeatedScalarIterator) {
TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) { TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.repeated_string().size()); EXPECT_EQ(0, test_model.repeated_string().size());
EXPECT_EQ(0, test_model.mutable_repeated_string()->size()); EXPECT_EQ(0, test_model.mutable_repeated_string()->size());
@ -527,7 +529,7 @@ TEST(CppGeneratedCode, RepeatedFieldProxyForStrings) {
TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) { TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.child_models().size()); EXPECT_EQ(0, test_model.child_models().size());
ChildModel1 child1; ChildModel1 child1;
child1.set_child_str1(kTestStr1); child1.set_child_str1(kTestStr1);
@ -572,7 +574,7 @@ TEST(CppGeneratedCode, RepeatedFieldProxyForMessages) {
TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) { TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.child_models().size()); EXPECT_EQ(0, test_model.child_models().size());
ChildModel1 child1; ChildModel1 child1;
child1.set_child_str1(kTestStr1); child1.set_child_str1(kTestStr1);
@ -585,7 +587,7 @@ TEST(CppGeneratedCode, EmptyRepeatedFieldProxyForMessages) {
TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) { TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.child_models().size()); EXPECT_EQ(0, test_model.child_models().size());
ChildModel1 child1; ChildModel1 child1;
child1.set_child_str1(kTestStr1); child1.set_child_str1(kTestStr1);
@ -603,7 +605,7 @@ TEST(CppGeneratedCode, RepeatedFieldProxyForMessagesIndexOperator) {
TEST(CppGeneratedCode, RepeatedStrings) { TEST(CppGeneratedCode, RepeatedStrings) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.repeated_string_size()); EXPECT_EQ(0, test_model.repeated_string_size());
// Should be able to clear repeated field when empty. // Should be able to clear repeated field when empty.
test_model.mutable_repeated_string()->clear(); test_model.mutable_repeated_string()->clear();
@ -626,11 +628,11 @@ TEST(CppGeneratedCode, MessageMapInt32KeyMessageValue) {
const int key_test_value = 3; const int key_test_value = 3;
::hpb::Arena arena; ::hpb::Arena arena;
::hpb::Arena child_arena; ::hpb::Arena child_arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.child_map_size()); EXPECT_EQ(0, test_model.child_map_size());
test_model.clear_child_map(); test_model.clear_child_map();
EXPECT_EQ(0, test_model.child_map_size()); EXPECT_EQ(0, test_model.child_map_size());
auto child_model1 = ::protos::CreateMessage<ChildModel1>(child_arena); auto child_model1 = ::hpb::CreateMessage<ChildModel1>(child_arena);
child_model1.set_child_str1("abc"); child_model1.set_child_str1("abc");
test_model.set_child_map(key_test_value, child_model1); test_model.set_child_map(key_test_value, child_model1);
auto map_result = test_model.get_child_map(key_test_value); auto map_result = test_model.get_child_map(key_test_value);
@ -647,7 +649,7 @@ TEST(CppGeneratedCode, MessageMapInt32KeyMessageValue) {
TEST(CppGeneratedCode, MessageMapStringKeyAndStringValue) { TEST(CppGeneratedCode, MessageMapStringKeyAndStringValue) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.str_to_str_map_size()); EXPECT_EQ(0, test_model.str_to_str_map_size());
test_model.clear_str_to_str_map(); test_model.clear_str_to_str_map();
EXPECT_EQ(0, test_model.str_to_str_map_size()); EXPECT_EQ(0, test_model.str_to_str_map_size());
@ -663,7 +665,7 @@ TEST(CppGeneratedCode, MessageMapStringKeyAndStringValue) {
TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) { TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) {
::hpb::Arena arena; ::hpb::Arena arena;
auto test_model = ::protos::CreateMessage<TestModel>(arena); auto test_model = ::hpb::CreateMessage<TestModel>(arena);
EXPECT_EQ(0, test_model.str_to_int_map_size()); EXPECT_EQ(0, test_model.str_to_int_map_size());
test_model.clear_str_to_int_map(); test_model.clear_str_to_int_map();
EXPECT_EQ(0, test_model.str_to_int_map_size()); EXPECT_EQ(0, test_model.str_to_int_map_size());
@ -681,26 +683,26 @@ TEST(CppGeneratedCode, MessageMapStringKeyAndInt32Value) {
TEST(CppGeneratedCode, HasExtension) { TEST(CppGeneratedCode, HasExtension) {
TestModel model; TestModel model;
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
} }
TEST(CppGeneratedCode, HasExtensionPtr) { TEST(CppGeneratedCode, HasExtensionPtr) {
TestModel model; TestModel model;
EXPECT_EQ(false, ::protos::HasExtension(model.recursive_child(), theme)); EXPECT_EQ(false, ::hpb::HasExtension(model.recursive_child(), theme));
} }
TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) { TEST(CppGeneratedCode, ClearExtensionWithEmptyExtension) {
TestModel model; TestModel model;
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
::protos::ClearExtension(&model, theme); ::hpb::ClearExtension(&model, theme);
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
} }
TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) { TEST(CppGeneratedCode, ClearExtensionWithEmptyExtensionPtr) {
TestModel model; TestModel model;
::protos::Ptr<TestModel> recursive_child = model.mutable_recursive_child(); ::hpb::Ptr<TestModel> recursive_child = model.mutable_recursive_child();
::protos::ClearExtension(recursive_child, theme); ::hpb::ClearExtension(recursive_child, theme);
EXPECT_EQ(false, ::protos::HasExtension(recursive_child, theme)); EXPECT_EQ(false, ::hpb::HasExtension(recursive_child, theme));
} }
TEST(CppGeneratedCode, SetExtension) { TEST(CppGeneratedCode, SetExtension) {
@ -710,44 +712,42 @@ TEST(CppGeneratedCode, SetExtension) {
// Use a nested scope to make sure the arenas are fused correctly. // Use a nested scope to make sure the arenas are fused correctly.
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
prior_message = ::protos::internal::GetInternalMsg(&extension1); prior_message = ::hpb::internal::GetInternalMsg(&extension1);
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
EXPECT_EQ( EXPECT_EQ(true,
true, ::hpb::SetExtension(&model, theme, std::move(extension1)).ok());
::protos::SetExtension(&model, theme, std::move(extension1)).ok());
} }
EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); EXPECT_EQ(true, ::hpb::HasExtension(&model, theme));
auto ext = ::protos::GetExtension(&model, theme); auto ext = ::protos::GetExtension(&model, theme);
EXPECT_TRUE(ext.ok()); EXPECT_TRUE(ext.ok());
EXPECT_EQ(::protos::internal::GetInternalMsg(*ext), prior_message); EXPECT_EQ(::hpb::internal::GetInternalMsg(*ext), prior_message);
} }
TEST(CppGeneratedCode, SetExtensionWithPtr) { TEST(CppGeneratedCode, SetExtensionWithPtr) {
::hpb::Arena arena_model; ::hpb::Arena arena_model;
::protos::Ptr<TestModel> model = ::hpb::Ptr<TestModel> model = ::hpb::CreateMessage<TestModel>(arena_model);
::protos::CreateMessage<TestModel>(arena_model);
void* prior_message; void* prior_message;
{ {
// Use a nested scope to make sure the arenas are fused correctly. // Use a nested scope to make sure the arenas are fused correctly.
::hpb::Arena arena; ::hpb::Arena arena;
::protos::Ptr<ThemeExtension> extension1 = ::hpb::Ptr<ThemeExtension> extension1 =
::protos::CreateMessage<ThemeExtension>(arena); ::hpb::CreateMessage<ThemeExtension>(arena);
extension1->set_ext_name("Hello World"); extension1->set_ext_name("Hello World");
prior_message = ::protos::internal::GetInternalMsg(extension1); prior_message = ::hpb::internal::GetInternalMsg(extension1);
EXPECT_EQ(false, ::protos::HasExtension(model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(model, theme));
auto res = ::protos::SetExtension(model, theme, extension1); auto res = ::hpb::SetExtension(model, theme, extension1);
EXPECT_EQ(true, res.ok()); EXPECT_EQ(true, res.ok());
} }
EXPECT_EQ(true, ::protos::HasExtension(model, theme)); EXPECT_EQ(true, ::hpb::HasExtension(model, theme));
auto ext = ::protos::GetExtension(model, theme); auto ext = ::protos::GetExtension(model, theme);
EXPECT_TRUE(ext.ok()); EXPECT_TRUE(ext.ok());
EXPECT_NE(::protos::internal::GetInternalMsg(*ext), prior_message); EXPECT_NE(::hpb::internal::GetInternalMsg(*ext), prior_message);
} }
#ifndef _MSC_VER #ifndef _MSC_VER
TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) { TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) {
::hpb::Arena arena; ::hpb::Arena arena;
::protos::Ptr<TestModel> model = ::protos::CreateMessage<TestModel>(arena); ::hpb::Ptr<TestModel> model = ::hpb::CreateMessage<TestModel>(arena);
ThemeExtension extension1; ThemeExtension extension1;
ContainerExtension extension2; ContainerExtension extension2;
@ -755,52 +755,52 @@ TEST(CppGeneratedCode, SetExtensionShouldNotCompileForWrongType) {
return Requires<decltype(model)>(l); return Requires<decltype(model)>(l);
}; };
EXPECT_TRUE(canSetExtension( EXPECT_TRUE(canSetExtension(
[](auto p) -> decltype(::protos::SetExtension(p, theme, extension1)) {})); [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension1)) {}));
// Wrong extension value type should fail to compile. // Wrong extension value type should fail to compile.
EXPECT_TRUE(!canSetExtension( EXPECT_TRUE(!canSetExtension(
[](auto p) -> decltype(::protos::SetExtension(p, theme, extension2)) {})); [](auto p) -> decltype(::hpb::SetExtension(p, theme, extension2)) {}));
// Wrong extension id with correct extension type should fail to compile. // Wrong extension id with correct extension type should fail to compile.
EXPECT_TRUE( EXPECT_TRUE(
!canSetExtension([](auto p) -> decltype(::protos::SetExtension( !canSetExtension([](auto p) -> decltype(::hpb::SetExtension(
p, container_ext, extension1)) {})); p, container_ext, extension1)) {}));
} }
#endif #endif
TEST(CppGeneratedCode, SetExtensionWithPtrSameArena) { TEST(CppGeneratedCode, SetExtensionWithPtrSameArena) {
::hpb::Arena arena; ::hpb::Arena arena;
::protos::Ptr<TestModel> model = ::protos::CreateMessage<TestModel>(arena); ::hpb::Ptr<TestModel> model = ::hpb::CreateMessage<TestModel>(arena);
void* prior_message; void* prior_message;
{ {
// Use a nested scope to make sure the arenas are fused correctly. // Use a nested scope to make sure the arenas are fused correctly.
::protos::Ptr<ThemeExtension> extension1 = ::hpb::Ptr<ThemeExtension> extension1 =
::protos::CreateMessage<ThemeExtension>(arena); ::hpb::CreateMessage<ThemeExtension>(arena);
extension1->set_ext_name("Hello World"); extension1->set_ext_name("Hello World");
prior_message = ::protos::internal::GetInternalMsg(extension1); prior_message = ::hpb::internal::GetInternalMsg(extension1);
EXPECT_EQ(false, ::protos::HasExtension(model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(model, theme));
auto res = ::protos::SetExtension(model, theme, extension1); auto res = ::hpb::SetExtension(model, theme, extension1);
EXPECT_EQ(true, res.ok()); EXPECT_EQ(true, res.ok());
} }
EXPECT_EQ(true, ::protos::HasExtension(model, theme)); EXPECT_EQ(true, ::hpb::HasExtension(model, theme));
auto ext = ::protos::GetExtension(model, theme); auto ext = ::protos::GetExtension(model, theme);
EXPECT_TRUE(ext.ok()); EXPECT_TRUE(ext.ok());
EXPECT_NE(::protos::internal::GetInternalMsg(*ext), prior_message); EXPECT_NE(::hpb::internal::GetInternalMsg(*ext), prior_message);
} }
TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) { TEST(CppGeneratedCode, SetExtensionFusingFailureShouldCopy) {
// Use an initial block to disallow fusing. // Use an initial block to disallow fusing.
char initial_block[1000]; char initial_block[1000];
protos::Arena arena(initial_block, sizeof(initial_block)); hpb::Arena arena(initial_block, sizeof(initial_block));
protos::Ptr<TestModel> model = protos::CreateMessage<TestModel>(arena); hpb::Ptr<TestModel> model = ::hpb::CreateMessage<TestModel>(arena);
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
ASSERT_FALSE( ASSERT_FALSE(
upb_Arena_Fuse(arena.ptr(), ::protos::internal::GetArena(&extension1))); upb_Arena_Fuse(arena.ptr(), ::hpb::internal::GetArena(&extension1)));
EXPECT_FALSE(::protos::HasExtension(model, theme)); EXPECT_FALSE(::hpb::HasExtension(model, theme));
auto status = ::protos::SetExtension(model, theme, std::move(extension1)); auto status = ::hpb::SetExtension(model, theme, std::move(extension1));
EXPECT_TRUE(status.ok()); EXPECT_TRUE(status.ok());
EXPECT_TRUE(::protos::HasExtension(model, theme)); EXPECT_TRUE(::hpb::HasExtension(model, theme));
EXPECT_TRUE(::protos::GetExtension(model, theme).ok()); EXPECT_TRUE(::protos::GetExtension(model, theme).ok());
} }
@ -808,10 +808,10 @@ TEST(CppGeneratedCode, SetExtensionShouldClone) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok());
extension1.set_ext_name("Goodbye"); extension1.set_ext_name("Goodbye");
EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); EXPECT_EQ(true, ::hpb::HasExtension(&model, theme));
auto ext = ::protos::GetExtension(&model, theme); auto ext = ::protos::GetExtension(&model, theme);
EXPECT_TRUE(ext.ok()); EXPECT_TRUE(ext.ok());
EXPECT_EQ((*ext)->ext_name(), "Hello World"); EXPECT_EQ((*ext)->ext_name(), "Hello World");
@ -821,12 +821,11 @@ TEST(CppGeneratedCode, SetExtensionShouldCloneConst) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
EXPECT_EQ( EXPECT_EQ(true,
true, ::hpb::SetExtension(&model, theme, std::as_const(extension1)).ok());
::protos::SetExtension(&model, theme, std::as_const(extension1)).ok());
extension1.set_ext_name("Goodbye"); extension1.set_ext_name("Goodbye");
EXPECT_EQ(true, ::protos::HasExtension(&model, theme)); EXPECT_EQ(true, ::hpb::HasExtension(&model, theme));
auto ext = ::protos::GetExtension(&model, theme); auto ext = ::protos::GetExtension(&model, theme);
EXPECT_TRUE(ext.ok()); EXPECT_TRUE(ext.ok());
EXPECT_EQ((*ext)->ext_name(), "Hello World"); EXPECT_EQ((*ext)->ext_name(), "Hello World");
@ -836,21 +835,19 @@ TEST(CppGeneratedCode, SetExtensionOnMutableChild) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(false, EXPECT_EQ(false, ::hpb::HasExtension(model.mutable_recursive_child(), theme));
::protos::HasExtension(model.mutable_recursive_child(), theme)); EXPECT_EQ(true, ::hpb::SetExtension(model.mutable_recursive_child(), theme,
EXPECT_EQ(true, ::protos::SetExtension(model.mutable_recursive_child(), theme,
extension1) extension1)
.ok()); .ok());
EXPECT_EQ(true, EXPECT_EQ(true, ::hpb::HasExtension(model.mutable_recursive_child(), theme));
::protos::HasExtension(model.mutable_recursive_child(), theme));
} }
TEST(CppGeneratedCode, GetExtension) { TEST(CppGeneratedCode, GetExtension) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(false, ::protos::HasExtension(&model, theme)); EXPECT_EQ(false, ::hpb::HasExtension(&model, theme));
EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok());
EXPECT_EQ("Hello World", EXPECT_EQ("Hello World",
::protos::GetExtension(&model, theme).value()->ext_name()); ::protos::GetExtension(&model, theme).value()->ext_name());
} }
@ -859,12 +856,12 @@ TEST(CppGeneratedCode, GetExtensionOnMutableChild) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
::protos::Ptr<TestModel> mutable_recursive_child = ::hpb::Ptr<TestModel> mutable_recursive_child =
model.mutable_recursive_child(); model.mutable_recursive_child();
EXPECT_EQ(false, ::protos::HasExtension(mutable_recursive_child, theme)); EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme));
EXPECT_EQ( EXPECT_EQ(
true, true,
::protos::SetExtension(mutable_recursive_child, theme, extension1).ok()); ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok());
EXPECT_EQ("Hello World", EXPECT_EQ("Hello World",
::protos::GetExtension(mutable_recursive_child, theme) ::protos::GetExtension(mutable_recursive_child, theme)
.value() .value()
@ -875,13 +872,13 @@ TEST(CppGeneratedCode, GetExtensionOnImmutableChild) {
TestModel model; TestModel model;
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
::protos::Ptr<TestModel> mutable_recursive_child = ::hpb::Ptr<TestModel> mutable_recursive_child =
model.mutable_recursive_child(); model.mutable_recursive_child();
EXPECT_EQ(false, ::protos::HasExtension(mutable_recursive_child, theme)); EXPECT_EQ(false, ::hpb::HasExtension(mutable_recursive_child, theme));
EXPECT_EQ( EXPECT_EQ(
true, true,
::protos::SetExtension(mutable_recursive_child, theme, extension1).ok()); ::hpb::SetExtension(mutable_recursive_child, theme, extension1).ok());
::protos::Ptr<const TestModel> recursive_child = model.recursive_child(); ::hpb::Ptr<const TestModel> recursive_child = model.recursive_child();
EXPECT_EQ("Hello World", EXPECT_EQ("Hello World",
::protos::GetExtension(recursive_child, theme).value()->ext_name()); ::protos::GetExtension(recursive_child, theme).value()->ext_name());
} }
@ -898,8 +895,7 @@ TEST(CppGeneratedCode, SerializeUsingArena) {
TEST(CppGeneratedCode, SerializeProxyUsingArena) { TEST(CppGeneratedCode, SerializeProxyUsingArena) {
::upb::Arena message_arena; ::upb::Arena message_arena;
TestModel::Proxy model_proxy = TestModel::Proxy model_proxy = ::hpb::CreateMessage<TestModel>(message_arena);
::protos::CreateMessage<TestModel>(message_arena);
model_proxy.set_str1("Hello World"); model_proxy.set_str1("Hello World");
::upb::Arena arena; ::upb::Arena arena;
absl::StatusOr<absl::string_view> bytes = absl::StatusOr<absl::string_view> bytes =
@ -913,7 +909,7 @@ TEST(CppGeneratedCode, SerializeNestedMessageUsingArena) {
TestModel model; TestModel model;
model.mutable_recursive_child()->set_str1("Hello World"); model.mutable_recursive_child()->set_str1("Hello World");
::upb::Arena arena; ::upb::Arena arena;
::protos::Ptr<const TestModel> child = model.recursive_child(); ::hpb::Ptr<const TestModel> child = model.recursive_child();
absl::StatusOr<absl::string_view> bytes = ::protos::Serialize(child, arena); absl::StatusOr<absl::string_view> bytes = ::protos::Serialize(child, arena);
EXPECT_EQ(true, bytes.ok()); EXPECT_EQ(true, bytes.ok());
TestModel parsed_model = ::protos::Parse<TestModel>(bytes.value()).value(); TestModel parsed_model = ::protos::Parse<TestModel>(bytes.value()).value();
@ -925,7 +921,7 @@ TEST(CppGeneratedCode, Parse) {
model.set_str1("Test123"); model.set_str1("Test123");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok());
::upb::Arena arena; ::upb::Arena arena;
auto bytes = ::protos::Serialize(&model, arena); auto bytes = ::protos::Serialize(&model, arena);
EXPECT_EQ(true, bytes.ok()); EXPECT_EQ(true, bytes.ok());
@ -939,12 +935,11 @@ TEST(CppGeneratedCode, ParseIntoPtrToModel) {
model.set_str1("Test123"); model.set_str1("Test123");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok());
::upb::Arena arena; ::upb::Arena arena;
auto bytes = ::protos::Serialize(&model, arena); auto bytes = ::protos::Serialize(&model, arena);
EXPECT_EQ(true, bytes.ok()); EXPECT_EQ(true, bytes.ok());
::protos::Ptr<TestModel> parsed_model = ::hpb::Ptr<TestModel> parsed_model = ::hpb::CreateMessage<TestModel>(arena);
::protos::CreateMessage<TestModel>(arena);
EXPECT_TRUE(::protos::Parse(parsed_model, bytes.value())); EXPECT_TRUE(::protos::Parse(parsed_model, bytes.value()));
EXPECT_EQ("Test123", parsed_model->str1()); EXPECT_EQ("Test123", parsed_model->str1());
// Should return an extension even if we don't pass ExtensionRegistry // Should return an extension even if we don't pass ExtensionRegistry
@ -957,14 +952,14 @@ TEST(CppGeneratedCode, ParseWithExtensionRegistry) {
model.set_str1("Test123"); model.set_str1("Test123");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("Hello World"); extension1.set_ext_name("Hello World");
EXPECT_EQ(true, ::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_EQ(true, ::hpb::SetExtension(&model, theme, extension1).ok());
EXPECT_EQ(true, ::protos::SetExtension( EXPECT_EQ(true, ::hpb::SetExtension(&model, ThemeExtension::theme_extension,
&model, ThemeExtension::theme_extension, extension1) extension1)
.ok()); .ok());
::upb::Arena arena; ::upb::Arena arena;
auto bytes = ::protos::Serialize(&model, arena); auto bytes = ::protos::Serialize(&model, arena);
EXPECT_EQ(true, bytes.ok()); EXPECT_EQ(true, bytes.ok());
::protos::ExtensionRegistry extensions( ::hpb::ExtensionRegistry extensions(
{&theme, &other_ext, &ThemeExtension::theme_extension}, arena); {&theme, &other_ext, &ThemeExtension::theme_extension}, arena);
TestModel parsed_model = TestModel parsed_model =
::protos::Parse<TestModel>(bytes.value(), extensions).value(); ::protos::Parse<TestModel>(bytes.value(), extensions).value();
@ -990,15 +985,15 @@ TEST(CppGeneratedCode, NameCollisions) {
TEST(CppGeneratedCode, SharedPointer) { TEST(CppGeneratedCode, SharedPointer) {
std::shared_ptr<TestModel> model = std::make_shared<TestModel>(); std::shared_ptr<TestModel> model = std::make_shared<TestModel>();
::upb::Arena arena; ::upb::Arena arena;
auto bytes = protos::Serialize(model.get(), arena); auto bytes = ::protos::Serialize(model.get(), arena);
EXPECT_TRUE(protos::Parse(model.get(), bytes.value())); EXPECT_TRUE(::protos::Parse(model.get(), bytes.value()));
} }
TEST(CppGeneratedCode, UniquePointer) { TEST(CppGeneratedCode, UniquePointer) {
auto model = std::make_unique<TestModel>(); auto model = std::make_unique<TestModel>();
::upb::Arena arena; ::upb::Arena arena;
auto bytes = protos::Serialize(model.get(), arena); auto bytes = ::protos::Serialize(model.get(), arena);
EXPECT_TRUE(protos::Parse(model.get(), bytes.value())); EXPECT_TRUE(::protos::Parse(model.get(), bytes.value()));
} }
TEST(CppGeneratedCode, Assignment) { TEST(CppGeneratedCode, Assignment) {
@ -1037,21 +1032,21 @@ TEST(CppGeneratedCode, PtrConstructor) {
TEST(CppGeneratedCode, MutableToProxy) { TEST(CppGeneratedCode, MutableToProxy) {
TestModel model; TestModel model;
::protos::Ptr<ChildModel1> child = model.mutable_child_model_1(); ::hpb::Ptr<ChildModel1> child = model.mutable_child_model_1();
(void)child; (void)child;
} }
TEST(CppGeneratedCode, ProxyToCProxy) { TEST(CppGeneratedCode, ProxyToCProxy) {
TestModel model; TestModel model;
::protos::Ptr<ChildModel1> child = model.mutable_child_model_1(); ::hpb::Ptr<ChildModel1> child = model.mutable_child_model_1();
::protos::Ptr<const ChildModel1> child2 = child; ::hpb::Ptr<const ChildModel1> child2 = child;
(void)child2; (void)child2;
} }
TEST(CppGeneratedCode, MutableAccessorsAreHiddenInCProxy) { TEST(CppGeneratedCode, MutableAccessorsAreHiddenInCProxy) {
TestModel model; TestModel model;
::protos::Ptr<TestModel> proxy = &model; ::hpb::Ptr<TestModel> proxy = &model;
::protos::Ptr<const TestModel> cproxy = proxy; ::hpb::Ptr<const TestModel> cproxy = proxy;
const auto test_const_accessors = [](auto p) { const auto test_const_accessors = [](auto p) {
// We don't want to run it, just check it compiles. // We don't want to run it, just check it compiles.
@ -1103,7 +1098,7 @@ TEST(CppGeneratedCode, MutableAccessorsAreHiddenInCProxy) {
test_mutable_accessors(cproxy, false); test_mutable_accessors(cproxy, false);
} }
bool ProxyToCProxyMethod(::protos::Ptr<const ChildModel1> child) { bool ProxyToCProxyMethod(::hpb::Ptr<const ChildModel1> child) {
return child->child_str1() == "text in child"; return child->child_str1() == "text in child";
} }
@ -1116,7 +1111,7 @@ TEST(CppGeneratedCode, PassProxyToCProxy) {
TEST(CppGeneratedCode, PtrImplicitConversion) { TEST(CppGeneratedCode, PtrImplicitConversion) {
TestModel model; TestModel model;
model.set_int64(5); model.set_int64(5);
::protos::Ptr<TestModel> model_ptr = &model; ::hpb::Ptr<TestModel> model_ptr = &model;
EXPECT_EQ(model_ptr->int64(), 5); EXPECT_EQ(model_ptr->int64(), 5);
} }
@ -1128,10 +1123,10 @@ TEST(CppGeneratedCode, ClearSubMessage) {
new_child->set_child_str1("text in child"); new_child->set_child_str1("text in child");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("name in extension"); extension1.set_ext_name("name in extension");
EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok());
EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1()); EXPECT_TRUE(model.mutable_child_model_1()->has_child_str1());
// Clear using Ptr<T> // Clear using Ptr<T>
::protos::ClearMessage(model.mutable_child_model_1()); ::hpb::ClearMessage(model.mutable_child_model_1());
EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1()); EXPECT_FALSE(model.mutable_child_model_1()->has_child_str1());
} }
@ -1145,14 +1140,14 @@ TEST(CppGeneratedCode, ClearMessage) {
new_child.value()->set_child_str1("text in child"); new_child.value()->set_child_str1("text in child");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("name in extension"); extension1.set_ext_name("name in extension");
EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok());
// Clear using T* // Clear using T*
::protos::ClearMessage(&model); ::hpb::ClearMessage(&model);
// Verify that scalars, repeated fields and extensions are cleared. // Verify that scalars, repeated fields and extensions are cleared.
EXPECT_FALSE(model.has_int64()); EXPECT_FALSE(model.has_int64());
EXPECT_FALSE(model.has_str2()); EXPECT_FALSE(model.has_str2());
EXPECT_TRUE(model.child_models().empty()); EXPECT_TRUE(model.child_models().empty());
EXPECT_FALSE(::protos::HasExtension(&model, theme)); EXPECT_FALSE(::hpb::HasExtension(&model, theme));
} }
TEST(CppGeneratedCode, CanInvokeClearMessageWithPtr) { TEST(CppGeneratedCode, CanInvokeClearMessageWithPtr) {
@ -1161,8 +1156,8 @@ TEST(CppGeneratedCode, CanInvokeClearMessageWithPtr) {
model.set_int64(5); model.set_int64(5);
auto new_child = model.add_child_models(); auto new_child = model.add_child_models();
// Clear using Ptr<T> // Clear using Ptr<T>
auto ptr = ::protos::Ptr<TestModel>(&model); auto ptr = ::hpb::Ptr<TestModel>(&model);
::protos::ClearMessage(ptr); ::hpb::ClearMessage(ptr);
// Successful clear // Successful clear
EXPECT_FALSE(model.has_int64()); EXPECT_FALSE(model.has_int64());
} }
@ -1173,19 +1168,19 @@ TEST(CppGeneratedCode, CanInvokeClearMessageWithRawPtr) {
model.set_int64(5); model.set_int64(5);
auto new_child = model.add_child_models(); auto new_child = model.add_child_models();
// Clear using T* // Clear using T*
::protos::ClearMessage(&model); ::hpb::ClearMessage(&model);
// Successful clear // Successful clear
EXPECT_FALSE(model.has_int64()); EXPECT_FALSE(model.has_int64());
} }
template <typename T> template <typename T>
bool CanCallClearMessage() { bool CanCallClearMessage() {
return Requires<T>([](auto x) -> decltype(::protos::ClearMessage(x)) {}); return Requires<T>([](auto x) -> decltype(::hpb::ClearMessage(x)) {});
} }
TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstPtr) { TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstPtr) {
EXPECT_TRUE(CanCallClearMessage<::protos::Ptr<TestModel>>()); EXPECT_TRUE(CanCallClearMessage<::hpb::Ptr<TestModel>>());
EXPECT_FALSE(CanCallClearMessage<::protos::Ptr<const TestModel>>()); EXPECT_FALSE(CanCallClearMessage<::hpb::Ptr<const TestModel>>());
} }
TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstRawPtr) { TEST(CppGeneratedCode, CannotInvokeClearMessageWithConstRawPtr) {
@ -1203,13 +1198,13 @@ TEST(CppGeneratedCode, DeepCopy) {
new_child.value()->set_child_str1("text in child"); new_child.value()->set_child_str1("text in child");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("name in extension"); extension1.set_ext_name("name in extension");
EXPECT_TRUE(::protos::SetExtension(&model, theme, extension1).ok()); EXPECT_TRUE(::hpb::SetExtension(&model, theme, extension1).ok());
TestModel target; TestModel target;
target.set_b1(true); target.set_b1(true);
::protos::DeepCopy(&model, &target); ::hpb::DeepCopy(&model, &target);
EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content "; EXPECT_FALSE(target.b1()) << "Target was not cleared before copying content ";
EXPECT_EQ(target.str2(), "Hello"); EXPECT_EQ(target.str2(), "Hello");
EXPECT_TRUE(::protos::HasExtension(&target, theme)); EXPECT_TRUE(::hpb::HasExtension(&target, theme));
} }
TEST(CppGeneratedCode, HasExtensionAndRegistry) { TEST(CppGeneratedCode, HasExtensionAndRegistry) {
@ -1222,16 +1217,16 @@ TEST(CppGeneratedCode, HasExtensionAndRegistry) {
new_child.value()->set_child_str1("text in child"); new_child.value()->set_child_str1("text in child");
ThemeExtension extension1; ThemeExtension extension1;
extension1.set_ext_name("name in extension"); extension1.set_ext_name("name in extension");
ASSERT_TRUE(::protos::SetExtension(&source, theme, extension1).ok()); ASSERT_TRUE(::hpb::SetExtension(&source, theme, extension1).ok());
// Now that we have a source model with extension data, serialize. // Now that we have a source model with extension data, serialize.
::hpb::Arena arena; ::hpb::Arena arena;
std::string data = std::string(::protos::Serialize(&source, arena).value()); std::string data = std::string(::protos::Serialize(&source, arena).value());
// Test with ExtensionRegistry // Test with ExtensionRegistry
::protos::ExtensionRegistry extensions({&theme}, arena); ::hpb::ExtensionRegistry extensions({&theme}, arena);
TestModel parsed_model = ::protos::Parse<TestModel>(data, extensions).value(); TestModel parsed_model = ::protos::Parse<TestModel>(data, extensions).value();
EXPECT_TRUE(::protos::HasExtension(&parsed_model, theme)); EXPECT_TRUE(::hpb::HasExtension(&parsed_model, theme));
} }
TEST(CppGeneratedCode, FieldNumberConstants) { TEST(CppGeneratedCode, FieldNumberConstants) {
@ -1239,6 +1234,10 @@ TEST(CppGeneratedCode, FieldNumberConstants) {
EXPECT_EQ(225, TestModel::kChildMapFieldNumber); EXPECT_EQ(225, TestModel::kChildMapFieldNumber);
} }
TEST(CppGeneratedCode, ExtensionFieldNumberConstant) {
EXPECT_EQ(12003, ::protos::ExtensionNumber(ThemeExtension::theme_extension));
}
TEST(CppGeneratedCode, ClearConstMessageShouldFailForConstChild) { TEST(CppGeneratedCode, ClearConstMessageShouldFailForConstChild) {
TestModel model; TestModel model;
EXPECT_FALSE(CanCallClearMessage<decltype(model.child_model_1())>()); EXPECT_FALSE(CanCallClearMessage<decltype(model.child_model_1())>());

@ -24,8 +24,7 @@ import java.io.IOException;
@CheckReturnValue @CheckReturnValue
final class ArrayDecoders { final class ArrayDecoders {
private ArrayDecoders() { private ArrayDecoders() {}
}
/** /**
* A helper used to return multiple values in a Java function. Java doesn't natively support * A helper used to return multiple values in a Java function. Java doesn't natively support

@ -287,13 +287,12 @@ public abstract class ByteString implements Iterable<Byte>, Serializable {
while (formerBytes.hasNext() && latterBytes.hasNext()) { while (formerBytes.hasNext() && latterBytes.hasNext()) {
int result = int result =
Integer.valueOf(toInt(formerBytes.nextByte())) Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte()));
.compareTo(toInt(latterBytes.nextByte()));
if (result != 0) { if (result != 0) {
return result; return result;
} }
} }
return Integer.valueOf(former.size()).compareTo(Integer.valueOf(latter.size())); return Integer.compare(former.size(), latter.size());
} }
}; };

@ -2343,7 +2343,7 @@ public final class Descriptors {
new Comparator<EnumValueDescriptor>() { new Comparator<EnumValueDescriptor>() {
@Override @Override
public int compare(EnumValueDescriptor o1, EnumValueDescriptor o2) { public int compare(EnumValueDescriptor o1, EnumValueDescriptor o2) {
return Integer.valueOf(o1.getNumber()).compareTo(o2.getNumber()); return Integer.compare(o1.getNumber(), o2.getNumber());
} }
}; };

@ -264,7 +264,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
/** /**
* Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}. * Useful for implementing {@link Message.Builder#setField(Descriptors.FieldDescriptor,Object)}.
*/ */
@SuppressWarnings({"unchecked", "rawtypes"}) // Avoid iterator allocation.
@SuppressWarnings({"ForeachList", "ForeachListWithUserVar"})
public void setField(final T descriptor, Object value) { public void setField(final T descriptor, Object value) {
if (descriptor.isRepeated()) { if (descriptor.isRepeated()) {
if (!(value instanceof List)) { if (!(value instanceof List)) {
@ -274,10 +275,14 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
// Wrap the contents in a new list so that the caller cannot change // Wrap the contents in a new list so that the caller cannot change
// the list's contents after setting it. // the list's contents after setting it.
final List newList = new ArrayList<>(); List<?> list = (List<?>) value;
newList.addAll((List) value); int listSize = list.size();
for (final Object element : newList) { // Avoid extra allocations: no iterator, no intermediate array copy.
final List<Object> newList = new ArrayList<>(listSize);
for (int i = 0; i < listSize; i++) {
Object element = list.get(i);
verifyType(descriptor, element); verifyType(descriptor, element);
newList.add(element);
} }
value = newList; value = newList;
} else { } else {
@ -512,7 +517,8 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
} }
} }
@SuppressWarnings({"unchecked", "rawtypes"}) // Avoid iterator allocation.
@SuppressWarnings({"unchecked", "ForeachList", "ForeachListWithUserVar"})
private void mergeFromField(final Map.Entry<T, Object> entry) { private void mergeFromField(final Map.Entry<T, Object> entry) {
final T descriptor = entry.getKey(); final T descriptor = entry.getKey();
Object otherValue = entry.getValue(); Object otherValue = entry.getValue();
@ -523,11 +529,16 @@ final class FieldSet<T extends FieldSet.FieldDescriptorLite<T>> {
throw new IllegalStateException("Lazy fields can not be repeated"); throw new IllegalStateException("Lazy fields can not be repeated");
} }
Object value = getField(descriptor); Object value = getField(descriptor);
List<?> otherList = (List<?>) otherValue;
int otherListSize = otherList.size();
if (value == null) { if (value == null) {
value = new ArrayList<>(); value = new ArrayList<>(otherListSize);
} }
for (Object element : (List) otherValue) { List<Object> list = (List<Object>) value;
((List) value).add(cloneIfMutable(element)); // Avoid iterator allocation.
for (int i = 0; i < otherListSize; i++) {
Object element = otherList.get(i);
list.add(cloneIfMutable(element));
} }
fields.put(descriptor, value); fields.put(descriptor, value);
} else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) { } else if (descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE) {

@ -843,7 +843,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
* the generated API only allows us to access it as a map. This method returns the underlying * the generated API only allows us to access it as a map. This method returns the underlying
* map field directly and thus enables us to access the map field as a list. * map field directly and thus enables us to access the map field as a list.
*/ */
@SuppressWarnings({"unused", "rawtypes"}) @SuppressWarnings("unused")
protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) { protected MapFieldReflectionAccessor internalGetMapFieldReflection(int fieldNumber) {
return internalGetMapField(fieldNumber); return internalGetMapField(fieldNumber);
} }
@ -858,7 +858,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
} }
/** Like {@link #internalGetMapFieldReflection} but return a mutable version. */ /** Like {@link #internalGetMapFieldReflection} but return a mutable version. */
@SuppressWarnings({"unused", "rawtypes"}) @SuppressWarnings("unused")
protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(int fieldNumber) { protected MapFieldReflectionAccessor internalGetMutableMapFieldReflection(int fieldNumber) {
return internalGetMutableMapField(fieldNumber); return internalGetMutableMapField(fieldNumber);
} }
@ -2054,8 +2054,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
new RepeatedEnumFieldAccessor( new RepeatedEnumFieldAccessor(
field, camelCaseNames[i], messageClass, builderClass); field, camelCaseNames[i], messageClass, builderClass);
} else { } else {
fields[i] = fields[i] = new RepeatedFieldAccessor(camelCaseNames[i], messageClass, builderClass);
new RepeatedFieldAccessor(field, camelCaseNames[i], messageClass, builderClass);
} }
} else { } else {
if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) { if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
@ -2611,7 +2610,6 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
protected final MethodInvoker invoker; protected final MethodInvoker invoker;
RepeatedFieldAccessor( RepeatedFieldAccessor(
final FieldDescriptor descriptor,
final String camelCaseName, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass, final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder<?>> builderClass) { final Class<? extends Builder<?>> builderClass) {
@ -2916,7 +2914,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
final String camelCaseName, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass, final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder<?>> builderClass) { final Class<? extends Builder<?>> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass); super(camelCaseName, messageClass, builderClass);
enumDescriptor = descriptor.getEnumType(); enumDescriptor = descriptor.getEnumType();
@ -3112,7 +3110,7 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial
final String camelCaseName, final String camelCaseName,
final Class<? extends GeneratedMessage> messageClass, final Class<? extends GeneratedMessage> messageClass,
final Class<? extends Builder<?>> builderClass) { final Class<? extends Builder<?>> builderClass) {
super(descriptor, camelCaseName, messageClass, builderClass); super(camelCaseName, messageClass, builderClass);
newBuilderMethod = getMethodOrDie(type, "newBuilder"); newBuilderMethod = getMethodOrDie(type, "newBuilder");
getBuilderMethodBuilder = getBuilderMethodBuilder =

@ -132,7 +132,7 @@ public class InvalidProtocolBufferException extends IOException {
static InvalidProtocolBufferException recursionLimitExceeded() { static InvalidProtocolBufferException recursionLimitExceeded() {
return new InvalidProtocolBufferException( return new InvalidProtocolBufferException(
"Protocol message had too many levels of nesting. May be malicious. " "Protocol message had too many levels of nesting. May be malicious. "
+ "Use CodedInputStream.setRecursionLimit() to increase the depth limit."); + "Use setRecursionLimit() to increase the recursion depth limit.");
} }
static InvalidProtocolBufferException sizeLimitExceeded() { static InvalidProtocolBufferException sizeLimitExceeded() {

@ -3006,6 +3006,7 @@ final class MessageSchema<T> implements Schema<T> {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message); unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
} }
// Unknown field. // Unknown field.
if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { if (unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
continue; continue;
} }
@ -3381,6 +3382,7 @@ final class MessageSchema<T> implements Schema<T> {
if (unknownFields == null) { if (unknownFields == null) {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message); unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
} }
if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
return; return;
} }
@ -3397,6 +3399,7 @@ final class MessageSchema<T> implements Schema<T> {
if (unknownFields == null) { if (unknownFields == null) {
unknownFields = unknownFieldSchema.getBuilderFromMessage(message); unknownFields = unknownFieldSchema.getBuilderFromMessage(message);
} }
if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) { if (!unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader)) {
return; return;
} }

@ -278,6 +278,7 @@ final class MessageSetSchema<T> implements Schema<T> {
reader, extension, extensionRegistry, extensions); reader, extension, extensionRegistry, extensions);
return true; return true;
} else { } else {
return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader); return unknownFieldSchema.mergeOneFieldFrom(unknownFields, reader);
} }
} else { } else {

@ -449,11 +449,11 @@ public final class TextFormat {
} }
switch (fieldType) { switch (fieldType) {
case BOOLEAN: case BOOLEAN:
return Boolean.valueOf((boolean) getKey()).compareTo((boolean) b.getKey()); return ((Boolean) getKey()).compareTo((Boolean) b.getKey());
case LONG: case LONG:
return Long.valueOf((long) getKey()).compareTo((long) b.getKey()); return ((Long) getKey()).compareTo((Long) b.getKey());
case INT: case INT:
return Integer.valueOf((int) getKey()).compareTo((int) b.getKey()); return ((Integer) getKey()).compareTo((Integer) b.getKey());
case STRING: case STRING:
String aString = (String) getKey(); String aString = (String) getKey();
String bString = (String) b.getKey(); String bString = (String) b.getKey();

@ -55,7 +55,6 @@ abstract class UnknownFieldSchema<T, B> {
/** Marks unknown fields as immutable. */ /** Marks unknown fields as immutable. */
abstract void makeImmutable(Object message); abstract void makeImmutable(Object message);
/** Merges one field into the unknown fields. */
final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException { final boolean mergeOneFieldFrom(B unknownFields, Reader reader) throws IOException {
int tag = reader.getTag(); int tag = reader.getTag();
int fieldNumber = WireFormat.getTagFieldNumber(tag); int fieldNumber = WireFormat.getTagFieldNumber(tag);
@ -88,7 +87,7 @@ abstract class UnknownFieldSchema<T, B> {
} }
} }
final void mergeFrom(B unknownFields, Reader reader) throws IOException { private final void mergeFrom(B unknownFields, Reader reader) throws IOException {
while (true) { while (true) {
if (reader.getFieldNumber() == Reader.READ_DONE if (reader.getFieldNumber() == Reader.READ_DONE
|| !mergeOneFieldFrom(unknownFields, reader)) { || !mergeOneFieldFrom(unknownFields, reader)) {

@ -80,7 +80,7 @@ public class UnknownFieldSetTest {
// ================================================================= // =================================================================
@Test @Test
public void testFieldBuildersAreReusable() { public void testFixed32FieldBuildersAreReusable() {
UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder(); UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder();
fieldBuilder.addFixed32(10); fieldBuilder.addFixed32(10);
UnknownFieldSet.Field first = fieldBuilder.build(); UnknownFieldSet.Field first = fieldBuilder.build();
@ -92,6 +92,64 @@ public class UnknownFieldSetTest {
assertThat(first).isNotEqualTo(third); assertThat(first).isNotEqualTo(third);
} }
@Test
public void testFixed64FieldBuildersAreReusable() {
UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder();
fieldBuilder.addFixed64(10);
UnknownFieldSet.Field first = fieldBuilder.build();
UnknownFieldSet.Field second = fieldBuilder.build();
fieldBuilder.addFixed64(11);
UnknownFieldSet.Field third = fieldBuilder.build();
assertThat(first).isEqualTo(second);
assertThat(first).isNotEqualTo(third);
}
@Test
public void testVarintFieldBuildersAreReusable() {
UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder();
fieldBuilder.addVarint(10);
UnknownFieldSet.Field first = fieldBuilder.build();
UnknownFieldSet.Field second = fieldBuilder.build();
fieldBuilder.addVarint(11);
UnknownFieldSet.Field third = fieldBuilder.build();
assertThat(first).isEqualTo(second);
assertThat(first).isNotEqualTo(third);
}
@Test
public void testLengthDelimitedFieldBuildersAreReusable() {
UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder();
fieldBuilder.addLengthDelimited(ByteString.copyFromUtf8("foo"));
UnknownFieldSet.Field first = fieldBuilder.build();
UnknownFieldSet.Field second = fieldBuilder.build();
fieldBuilder.addLengthDelimited(ByteString.copyFromUtf8("bar"));
UnknownFieldSet.Field third = fieldBuilder.build();
assertThat(first).isEqualTo(second);
assertThat(first).isNotEqualTo(third);
}
@Test
public void testGroupFieldBuildersAreReusable() {
UnknownFieldSet.Field.Builder fieldBuilder = UnknownFieldSet.Field.newBuilder();
fieldBuilder.addGroup(
UnknownFieldSet.newBuilder()
.addField(10, UnknownFieldSet.Field.newBuilder().addVarint(10).build())
.build());
UnknownFieldSet.Field first = fieldBuilder.build();
UnknownFieldSet.Field second = fieldBuilder.build();
fieldBuilder.addGroup(
UnknownFieldSet.newBuilder()
.addField(11, UnknownFieldSet.Field.newBuilder().addVarint(11).build())
.build());
UnknownFieldSet.Field third = fieldBuilder.build();
assertThat(first).isEqualTo(second);
assertThat(first).isNotEqualTo(third);
}
@Test @Test
public void testClone() { public void testClone() {
UnknownFieldSet.Builder unknownSetBuilder = UnknownFieldSet.newBuilder(); UnknownFieldSet.Builder unknownSetBuilder = UnknownFieldSet.newBuilder();

@ -276,6 +276,7 @@ kt_jvm_library(
"//java/core:test_util", "//java/core:test_util",
"@maven//:com_google_truth_truth", "@maven//:com_google_truth_truth",
"@maven//:junit_junit", "@maven//:junit_junit",
"@rules_kotlin//kotlin/compiler:kotlin-reflect",
], ],
) )

@ -26,12 +26,14 @@ import protobuf_unittest.UnittestProto.TestAllTypes.NestedEnum
import protobuf_unittest.UnittestProto.TestEmptyMessage import protobuf_unittest.UnittestProto.TestEmptyMessage
import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions import protobuf_unittest.UnittestProto.TestEmptyMessageWithExtensions
import protobuf_unittest.copy import protobuf_unittest.copy
import protobuf_unittest.deprecatedMessageOrNull
import protobuf_unittest.foreignMessage import protobuf_unittest.foreignMessage
import protobuf_unittest.optionalGroupExtension import protobuf_unittest.optionalGroupExtension
import protobuf_unittest.optionalNestedMessageOrNull import protobuf_unittest.optionalNestedMessageOrNull
import protobuf_unittest.repeatedGroupExtension import protobuf_unittest.repeatedGroupExtension
import protobuf_unittest.testAllExtensions import protobuf_unittest.testAllExtensions
import protobuf_unittest.testAllTypes import protobuf_unittest.testAllTypes
import protobuf_unittest.testDeprecatedFields
import protobuf_unittest.testEmptyMessage import protobuf_unittest.testEmptyMessage
import protobuf_unittest.testEmptyMessageWithExtensions import protobuf_unittest.testEmptyMessageWithExtensions
import protobuf_unittest.testEnumMap import protobuf_unittest.testEnumMap
@ -959,4 +961,15 @@ class Proto2Test {
assertThat(someNestedMessage.optionalNestedMessageOrNull) assertThat(someNestedMessage.optionalNestedMessageOrNull)
.isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 }) .isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
} }
@Test
fun testDeprecated() {
val testInstance =
protobuf_unittest.UnittestProto.TestDeprecatedFields.getDefaultInstance()
assertThat(testInstance::deprecatedMessageOrNull.annotations.any { it is Deprecated }).isTrue()
val unused = testDeprecatedFields {
assertThat(::deprecatedMessage.annotations.any { it is Deprecated }).isTrue()
}
}
} }

@ -10,12 +10,14 @@ package com.google.protobuf;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage; import static com.google.common.truth.Truth.assertWithMessage;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.junit.Assert.assertThrows;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes; import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.UnittestImportLite.ImportEnumLite; import com.google.protobuf.UnittestImportLite.ImportEnumLite;
import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite; import com.google.protobuf.UnittestImportPublicLite.PublicImportMessageLite;
import com.google.protobuf.UnittestLite.ForeignEnumLite; import com.google.protobuf.UnittestLite.ForeignEnumLite;
import com.google.protobuf.UnittestLite.ForeignMessageLite; import com.google.protobuf.UnittestLite.ForeignMessageLite;
import com.google.protobuf.UnittestLite.RecursiveGroup;
import com.google.protobuf.UnittestLite.RecursiveMessage; import com.google.protobuf.UnittestLite.RecursiveMessage;
import com.google.protobuf.UnittestLite.TestAllExtensionsLite; import com.google.protobuf.UnittestLite.TestAllExtensionsLite;
import com.google.protobuf.UnittestLite.TestAllTypesLite; import com.google.protobuf.UnittestLite.TestAllTypesLite;
@ -50,6 +52,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;

@ -1790,7 +1790,7 @@ public class JsonFormat {
try { try {
BigDecimal decimalValue = new BigDecimal(json.getAsString()); BigDecimal decimalValue = new BigDecimal(json.getAsString());
BigInteger value = decimalValue.toBigIntegerExact(); BigInteger value = decimalValue.toBigIntegerExact();
if (value.signum() < 0 || value.compareTo(new BigInteger("FFFFFFFF", 16)) > 0) { if (value.signum() < 0 || value.compareTo(MAX_UINT32) > 0) {
throw new InvalidProtocolBufferException("Out of range uint32 value: " + json); throw new InvalidProtocolBufferException("Out of range uint32 value: " + json);
} }
return value.intValue(); return value.intValue();
@ -1802,6 +1802,7 @@ public class JsonFormat {
} }
} }
private static final BigInteger MAX_UINT32 = new BigInteger("FFFFFFFF", 16);
private static final BigInteger MAX_UINT64 = new BigInteger("FFFFFFFFFFFFFFFF", 16); private static final BigInteger MAX_UINT64 = new BigInteger("FFFFFFFFFFFFFFFF", 16);
private long parseUint64(JsonElement json) throws InvalidProtocolBufferException { private long parseUint64(JsonElement json) throws InvalidProtocolBufferException {

@ -13,6 +13,10 @@
#import "GPBUtilities_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h"
#import "GPBWireFormat.h" #import "GPBWireFormat.h"
// TODO: Consider using on other functions to reduce bloat when
// some compiler optimizations are enabled.
#define GPB_NOINLINE __attribute__((noinline))
NSString *const GPBCodedInputStreamException = GPBNSStringifySymbol(GPBCodedInputStreamException); NSString *const GPBCodedInputStreamException = GPBNSStringifySymbol(GPBCodedInputStreamException);
NSString *const GPBCodedInputStreamUnderlyingErrorKey = NSString *const GPBCodedInputStreamUnderlyingErrorKey =
@ -28,7 +32,8 @@ NSString *const GPBCodedInputStreamErrorDomain =
// int CodedInputStream::default_recursion_limit_ = 100; // int CodedInputStream::default_recursion_limit_ = 100;
static const NSUInteger kDefaultRecursionLimit = 100; static const NSUInteger kDefaultRecursionLimit = 100;
static void RaiseException(NSInteger code, NSString *reason) { GPB_NOINLINE
void GPBRaiseStreamError(NSInteger code, NSString *reason) {
NSDictionary *errorInfo = nil; NSDictionary *errorInfo = nil;
if ([reason length]) { if ([reason length]) {
errorInfo = @{GPBErrorReasonKey : reason}; errorInfo = @{GPBErrorReasonKey : reason};
@ -44,7 +49,7 @@ static void RaiseException(NSInteger code, NSString *reason) {
GPB_INLINE void CheckRecursionLimit(GPBCodedInputStreamState *state) { GPB_INLINE void CheckRecursionLimit(GPBCodedInputStreamState *state) {
if (state->recursionDepth >= kDefaultRecursionLimit) { if (state->recursionDepth >= kDefaultRecursionLimit) {
RaiseException(GPBCodedInputStreamErrorRecursionDepthExceeded, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorRecursionDepthExceeded, nil);
} }
} }
@ -56,19 +61,19 @@ GPB_INLINE void CheckFieldSize(uint64_t size) {
if (size > 0x7fffffff) { if (size > 0x7fffffff) {
// TODO: Maybe a different error code for this, but adding one is a breaking // TODO: Maybe a different error code for this, but adding one is a breaking
// change so reuse an existing one. // change so reuse an existing one.
RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil);
} }
} }
static void CheckSize(GPBCodedInputStreamState *state, size_t size) { static void CheckSize(GPBCodedInputStreamState *state, size_t size) {
size_t newSize = state->bufferPos + size; size_t newSize = state->bufferPos + size;
if (newSize > state->bufferSize) { if (newSize > state->bufferSize) {
RaiseException(GPBCodedInputStreamErrorInvalidSize, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSize, nil);
} }
if (newSize > state->currentLimit) { if (newSize > state->currentLimit) {
// Fast forward to end of currentLimit; // Fast forward to end of currentLimit;
state->bufferPos = state->currentLimit; state->bufferPos = state->currentLimit;
RaiseException(GPBCodedInputStreamErrorSubsectionLimitReached, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorSubsectionLimitReached, nil);
} }
} }
@ -110,7 +115,7 @@ static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
} }
shift += 7; shift += 7;
} }
RaiseException(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64"); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidVarInt, @"Invalid VarInt64");
return 0; return 0;
} }
@ -201,11 +206,11 @@ int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
state->lastTag = ReadRawVarint32(state); state->lastTag = ReadRawVarint32(state);
// Tags have to include a valid wireformat. // Tags have to include a valid wireformat.
if (!GPBWireFormatIsValidTag(state->lastTag)) { if (!GPBWireFormatIsValidTag(state->lastTag)) {
RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag."); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag.");
} }
// Zero is not a valid field number. // Zero is not a valid field number.
if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) { if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
RaiseException(GPBCodedInputStreamErrorInvalidTag, GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag,
@"A zero field number on the wire is invalid."); @"A zero field number on the wire is invalid.");
} }
return state->lastTag; return state->lastTag;
@ -231,7 +236,7 @@ NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state)
NSLog(@"UTF-8 failure, is some field type 'string' when it should be " NSLog(@"UTF-8 failure, is some field type 'string' when it should be "
@"'bytes'?"); @"'bytes'?");
#endif #endif
RaiseException(GPBCodedInputStreamErrorInvalidUTF8, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidUTF8, nil);
} }
} }
return result; return result;
@ -262,11 +267,65 @@ NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *sta
return result; return result;
} }
static void SkipToEndGroupInternal(GPBCodedInputStreamState *state, uint32_t endGroupTag) {
CheckRecursionLimit(state);
++state->recursionDepth;
while (YES) {
uint32_t tag = GPBCodedInputStreamReadTag(state);
if (tag == endGroupTag || tag == 0) {
GPBCodedInputStreamCheckLastTagWas(state, endGroupTag); // Will fail for end of input.
--state->recursionDepth;
return;
}
switch (GPBWireFormatGetTagWireType(tag)) {
case GPBWireFormatVarint:
(void)ReadRawVarint64(state);
break;
case GPBWireFormatFixed64:
SkipRawData(state, sizeof(uint64_t));
break;
case GPBWireFormatLengthDelimited: {
uint64_t size = ReadRawVarint64(state);
CheckFieldSize(size);
size_t size2 = (size_t)size; // Cast safe on 32bit because of CheckFieldSize() above.
SkipRawData(state, size2);
break;
}
case GPBWireFormatStartGroup:
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
GPBWireFormatEndGroup));
break;
case GPBWireFormatEndGroup:
GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unmatched end group");
break;
case GPBWireFormatFixed32:
SkipRawData(state, sizeof(uint32_t));
break;
}
}
}
// This doesn't include the start group, but it collects all bytes until the end group including
// the end group tag.
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber) {
// Better have just read the start of the group.
GPBCodedInputStreamCheckLastTagWas(state,
GPBWireFormatMakeTag(fieldNumber, GPBWireFormatStartGroup));
const uint8_t *start = state->bytes + state->bufferPos;
SkipToEndGroupInternal(state, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
// This will be after the end group tag.
const uint8_t *end = state->bytes + state->bufferPos;
return [[NSData alloc] initWithBytesNoCopy:(void *)start
length:(NSUInteger)(end - start)
freeWhenDone:NO];
}
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) { size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) {
byteLimit += state->bufferPos; byteLimit += state->bufferPos;
size_t oldLimit = state->currentLimit; size_t oldLimit = state->currentLimit;
if (byteLimit > oldLimit) { if (byteLimit > oldLimit) {
RaiseException(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidSubsectionLimit, nil);
} }
state->currentLimit = byteLimit; state->currentLimit = byteLimit;
return oldLimit; return oldLimit;
@ -286,7 +345,7 @@ BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value) { void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value) {
if (state->lastTag != value) { if (state->lastTag != value) {
RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read"); GPBRaiseStreamError(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read");
} }
} }

@ -53,6 +53,7 @@ typedef struct GPBCodedInputStreamState {
CF_EXTERN_C_BEGIN CF_EXTERN_C_BEGIN
void GPBRaiseStreamError(NSInteger code, NSString *reason);
int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state); int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state);
double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state); double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state);
@ -75,6 +76,9 @@ NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained)); __attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state) NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state)
__attribute((ns_returns_retained)); __attribute((ns_returns_retained));
NSData *GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(GPBCodedInputStreamState *state,
int32_t fieldNumber)
__attribute((ns_returns_retained));
size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit); size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit);
void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit); void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit);

@ -2085,6 +2085,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
- (BOOL)mergeFromData:(NSData *)data - (BOOL)mergeFromData:(NSData *)data
extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
error:(NSError **)errorPtr { error:(NSError **)errorPtr {
GPBBecomeVisibleToAutocreator(self);
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
@try { @try {
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0]; [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
@ -3683,4 +3684,23 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
return expected; return expected;
} }
NSData *GPBMessageUnknownFieldsData(GPBMessage *self) {
NSData *result = nil;
GPBUnknownFieldSet *unknownFields = self->unknownFields_;
if (unknownFields) {
if (self.descriptor.isWireFormat) {
NSMutableData *mutableData =
[NSMutableData dataWithLength:unknownFields.serializedSizeAsMessageSet];
GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:mutableData];
[unknownFields writeAsMessageSetTo:output];
[output flush];
[output release];
result = mutableData;
} else {
result = [unknownFields data];
}
}
return result;
}
#pragma clang diagnostic pop #pragma clang diagnostic pop

@ -81,4 +81,7 @@ void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary);
// autocreated reference to this message. // autocreated reference to this message.
void GPBClearMessageAutocreator(GPBMessage *self); void GPBClearMessageAutocreator(GPBMessage *self);
// The data (or null) from the unknown fields of a message;
NSData *GPBMessageUnknownFieldsData(GPBMessage *self);
CF_EXTERN_C_END CF_EXTERN_C_END

@ -154,7 +154,10 @@ static void CopyWorker(__unused const void *key, const void *value, void *contex
- (NSString *)description { - (NSString *)description {
NSMutableString *description = NSMutableString *description =
[NSMutableString stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self]; [NSMutableString stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" "); NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" ");
#pragma clang diagnostic pop
[description appendString:textFormat]; [description appendString:textFormat];
[description appendString:@"}"]; [description appendString:@"}"];
return description; return description;

@ -14,6 +14,7 @@
#import "GPBCodedOutputStream_PackagePrivate.h" #import "GPBCodedOutputStream_PackagePrivate.h"
#import "GPBDescriptor.h" #import "GPBDescriptor.h"
#import "GPBMessage.h" #import "GPBMessage.h"
#import "GPBMessage_PackagePrivate.h"
#import "GPBUnknownField.h" #import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownField_PackagePrivate.h"
@ -196,22 +197,8 @@ static BOOL MergeFromInputStream(GPBUnknownFields *self, GPBCodedInputStream *in
self = [super init]; self = [super init];
if (self) { if (self) {
fields_ = [[NSMutableArray alloc] init]; fields_ = [[NSMutableArray alloc] init];
// TODO: b/349146447 - Move off the legacy class and directly to the data once Message is NSData *data = GPBMessageUnknownFieldsData(message);
// updated. if (data) {
GPBUnknownFieldSet *legacyUnknownFields = [message unknownFields];
if (legacyUnknownFields) {
NSData *data;
if (message.descriptor.isWireFormat) {
NSMutableData *mutableData =
[NSMutableData dataWithLength:legacyUnknownFields.serializedSizeAsMessageSet];
GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:mutableData];
[legacyUnknownFields writeAsMessageSetTo:output];
[output flush];
[output release];
data = mutableData;
} else {
data = [legacyUnknownFields data];
}
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data]; GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
// Parse until the end of the data (tag will be zero). // Parse until the end of the data (tag will be zero).
if (!MergeFromInputStream(self, input, 0)) { if (!MergeFromInputStream(self, input, 0)) {

@ -40,7 +40,9 @@ NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *__nullable line
* @return An NSString with the TextFormat of the unknown field set. * @return An NSString with the TextFormat of the unknown field set.
**/ **/
NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *__nullable unknownSet, NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *__nullable unknownSet,
NSString *__nullable lineIndent); NSString *__nullable lineIndent)
__attribute__((deprecated("Use GPBTextFormatForMessage will include the unknown fields, and "
"GPBUnknownFieldSet it going away.")));
/** /**
* Checks if the given field number is set on a message. * Checks if the given field number is set on a message.

@ -5,7 +5,7 @@
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#import "GPBUtilities_PackagePrivate.h" #import "GPBUtilities.h"
#import <objc/runtime.h> #import <objc/runtime.h>
@ -15,6 +15,9 @@
#import "GPBMessage_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h"
#import "GPBUnknownField.h" #import "GPBUnknownField.h"
#import "GPBUnknownFieldSet.h" #import "GPBUnknownFieldSet.h"
#import "GPBUnknownField_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "GPBUtilities_PackagePrivate.h"
// Direct access is use for speed, to avoid even internally declaring things // Direct access is use for speed, to avoid even internally declaring things
// read/write, etc. The warning is enabled in the project to ensure code calling // read/write, etc. The warning is enabled in the project to ensure code calling
@ -1929,6 +1932,78 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSArra
} // for..in(activeExtensions) } // for..in(activeExtensions)
} }
static void AppendTextFormatForUnknownFields(GPBUnknownFields *ufs, NSMutableString *toStr,
NSString *lineIndent) {
#if defined(DEBUG) && DEBUG
NSCAssert(!ufs.empty, @"Internal Error: No unknown fields to format.");
#endif
// Extract the fields and sort them by field number. Use a stable sort and sort just by the field
// numbers, that way the output will still show the order the different types were added as well
// as maintaining the order within a give number/type pair (i.e. - repeated fields say in order).
NSMutableArray *sortedFields = [[NSMutableArray alloc] initWithCapacity:ufs.count];
for (GPBUnknownField *field in ufs) {
[sortedFields addObject:field];
}
[sortedFields
sortWithOptions:NSSortStable
usingComparator:^NSComparisonResult(GPBUnknownField *field1, GPBUnknownField *field2) {
int32_t fieldNumber1 = field1->number_;
int32_t fieldNumber2 = field2->number_;
if (fieldNumber1 < fieldNumber2) {
return NSOrderedAscending;
} else if (fieldNumber1 > fieldNumber2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
}];
NSString *subIndent = nil;
for (GPBUnknownField *field in sortedFields) {
int32_t fieldNumber = field->number_;
switch (field->type_) {
case GPBUnknownFieldTypeVarint:
[toStr appendFormat:@"%@%d: %llu\n", lineIndent, fieldNumber, field->storage_.intValue];
break;
case GPBUnknownFieldTypeFixed32:
[toStr appendFormat:@"%@%d: 0x%X\n", lineIndent, fieldNumber,
(uint32_t)field->storage_.intValue];
break;
case GPBUnknownFieldTypeFixed64:
[toStr appendFormat:@"%@%d: 0x%llX\n", lineIndent, fieldNumber, field->storage_.intValue];
break;
case GPBUnknownFieldTypeLengthDelimited:
[toStr appendFormat:@"%@%d: ", lineIndent, fieldNumber];
AppendBufferAsString(field->storage_.lengthDelimited, toStr);
[toStr appendString:@"\n"];
break;
case GPBUnknownFieldTypeGroup: {
GPBUnknownFields *group = field->storage_.group;
if (group.empty) {
[toStr appendFormat:@"%@%d: {}\n", lineIndent, fieldNumber];
} else {
[toStr appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
if (subIndent == nil) {
subIndent = [lineIndent stringByAppendingString:@" "];
}
AppendTextFormatForUnknownFields(group, toStr, subIndent);
[toStr appendFormat:@"%@}\n", lineIndent];
}
} break;
case GPBUnknownFieldTypeLegacy:
#if defined(DEBUG) && DEBUG
NSCAssert(
NO,
@"Internal error: Shouldn't have gotten a legacy field type in the unknown fields.");
#endif
break;
}
}
[subIndent release];
[sortedFields release];
}
static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr, static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
NSString *lineIndent) { NSString *lineIndent) {
GPBDescriptor *descriptor = [message descriptor]; GPBDescriptor *descriptor = [message descriptor];
@ -1951,11 +2026,12 @@ static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toS
} }
} }
NSString *unknownFieldsStr = GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent); GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message];
if ([unknownFieldsStr length] > 0) { if (ufs.count > 0) {
[toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent]; [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
[toStr appendString:unknownFieldsStr]; AppendTextFormatForUnknownFields(ufs, toStr, lineIndent);
} }
[ufs release];
} }
NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) { NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {

@ -6,12 +6,16 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "GPBTestUtilities.h"
#import "GPBCodedInputStream.h" #import "GPBCodedInputStream.h"
#import "GPBCodedInputStream_PackagePrivate.h"
#import "GPBCodedOutputStream.h" #import "GPBCodedOutputStream.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "GPBUtilities_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h"
#import "GPBWireFormat.h"
#import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h"
@interface CodedInputStreamTests : GPBTestCase @interface CodedInputStreamTests : GPBTestCase
@ -266,20 +270,55 @@
TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
NSData* rawBytes = message.data; NSData* rawBytes = message.data;
// Create two parallel inputs. Parse one as unknown fields while using TestEmptyMessage* empty = [TestEmptyMessage parseFromData:rawBytes error:NULL];
// skipField() to skip each field on the other. Expect the same tags. XCTAssertNotNil(empty);
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:empty] autorelease];
NSMutableArray<NSNumber*>* fieldNumbers = [NSMutableArray arrayWithCapacity:ufs.count];
for (GPBUnknownField* field in ufs) {
GPBWireFormat wireFormat;
switch (field.type) {
case GPBUnknownFieldTypeFixed32:
wireFormat = GPBWireFormatFixed32;
break;
case GPBUnknownFieldTypeFixed64:
wireFormat = GPBWireFormatFixed64;
break;
case GPBUnknownFieldTypeVarint:
wireFormat = GPBWireFormatVarint;
break;
case GPBUnknownFieldTypeLengthDelimited:
wireFormat = GPBWireFormatLengthDelimited;
break;
case GPBUnknownFieldTypeGroup:
wireFormat = GPBWireFormatStartGroup;
break;
case GPBUnknownFieldTypeLegacy:
XCTFail(@"Legacy field type not expected");
wireFormat = GPBWireFormatVarint;
break;
}
uint32_t tag = GPBWireFormatMakeTag(field.number, wireFormat);
[fieldNumbers addObject:@(tag)];
}
// Check the tags compared to what's in the UnknownFields to confirm the stream is
// skipping as expected (this covers the tags within a group also).
GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes]; GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes]; GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
GPBUnknownFieldSet* unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; GPBUnknownFieldSet* unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
NSUInteger idx = 0;
while (YES) { while (YES) {
int32_t tag = [input1 readTag]; int32_t tag = [input1 readTag];
XCTAssertEqual(tag, [input2 readTag]); XCTAssertEqual(tag, [input2 readTag]);
if (tag == 0) { if (tag == 0) {
XCTAssertEqual(idx, fieldNumbers.count);
break; break;
} }
XCTAssertEqual(tag, [fieldNumbers[idx] intValue]);
[unknownFields mergeFieldFrom:tag input:input1]; [unknownFields mergeFieldFrom:tag input:input1];
[input2 skipField:tag]; [input2 skipField:tag];
++idx;
} }
} }
@ -444,4 +483,102 @@
} }
} }
- (void)assertReadByteToEndGroupFails:(NSData*)data {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
XCTAssertThrows(GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag)));
}
- (void)assertReadByteToEndGroup:(NSData*)data value:(NSData*)value {
GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
uint32_t tag = [input readTag];
NSData* readValue = GPBCodedInputStreamReadRetainedBytesToEndGroupNoCopy(
&input->state_, GPBWireFormatGetTagFieldNumber(tag));
XCTAssertNotNil(readValue);
XCTAssertEqualObjects(readValue, value);
[readValue release];
}
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testBytesToEndGroup {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
[self assertReadByteToEndGroup:bytes(35, 36) value:bytes(36)]; // empty group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 36) value:bytes(8, 1, 36)]; // varint
[self assertReadByteToEndGroup:bytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36) // fixed32
value:bytes(21, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36) // fixed64
value:bytes(25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12, 36)];
[self assertReadByteToEndGroup:bytes(35, 50, 0, 36)
value:bytes(50, 0, 36)]; // length delimited, length 0
[self assertReadByteToEndGroup:bytes(35, 50, 1, 42, 36)
value:bytes(50, 1, 42, 36)]; // length delimited, length 1, byte 42
[self assertReadByteToEndGroup:bytes(35, 43, 44, 36) value:bytes(43, 44, 36)]; // Sub group
[self assertReadByteToEndGroup:bytes(35, 8, 1, 43, 8, 1, 44,
36) // varint and sub group with varint
value:bytes(8, 1, 43, 8, 1, 44, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 0, 36)]; // Invalid field number
[self assertReadByteToEndGroupFails:bytes(35, 15, 36)]; // Invalid wire type
[self assertReadByteToEndGroupFails:bytes(35, 21, 0x78, 0x56, 0x34)]; // truncated fixed32
[self assertReadByteToEndGroupFails:bytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)]; // truncated fixed64
// Mising end group
[self assertReadByteToEndGroupFails:bytes(35)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1)];
[self assertReadByteToEndGroupFails:bytes(35, 43)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1)];
// Wrong end group
[self assertReadByteToEndGroupFails:bytes(35, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 8, 1, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 36)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 44, 44)];
[self assertReadByteToEndGroupFails:bytes(35, 43, 8, 1, 44, 44)];
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
[self assertReadByteToEndGroup:testData
value:[testData subdataWithRange:NSMakeRange(1, testData.length - 1)]];
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
[self assertReadByteToEndGroupFails:testData];
}
@end @end

@ -419,6 +419,17 @@
// All the values should be in unknown fields. // All the values should be in unknown fields.
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg];
XCTAssertEqual(ufs.count, 3U);
uint64_t varint;
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OptionalEnum varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_RepeatedEnumArray varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
XCTAssertTrue([ufs getFirst:Message2_FieldNumber_OneofEnum varint:&varint]);
XCTAssertEqual(varint, (uint64_t)Message3_Enum_Extra3);
[ufs release];
GPBUnknownFieldSet *unknownFields = msg.unknownFields; GPBUnknownFieldSet *unknownFields = msg.unknownFields;
XCTAssertEqual([unknownFields countOfFields], 3U); XCTAssertEqual([unknownFields countOfFields], 3U);
@ -1398,6 +1409,9 @@
int32_t val = -1; int32_t val = -1;
XCTAssertTrue([msg1.knownMapField getEnum:&val forKey:0]); XCTAssertTrue([msg1.knownMapField getEnum:&val forKey:0]);
XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo); XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo);
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:msg1];
XCTAssertEqual(ufs.count, 1U);
[ufs release];
XCTAssertEqual(msg1.unknownFields.countOfFields, 1U); XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
data = [msg1 data]; data = [msg1 data];
@ -1410,6 +1424,9 @@
XCTAssertEqual(msg2.unknownMapField.count, 1U); XCTAssertEqual(msg2.unknownMapField.count, 1U);
XCTAssertTrue([msg2.unknownMapField getEnum:&val forKey:0]); XCTAssertTrue([msg2.unknownMapField getEnum:&val forKey:0]);
XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra); XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra);
ufs = [[GPBUnknownFields alloc] initFromMessage:msg2];
XCTAssertTrue(ufs.empty);
[ufs release];
XCTAssertEqual(msg2.unknownFields.countOfFields, 0U); XCTAssertEqual(msg2.unknownFields.countOfFields, 0U);
XCTAssertEqualObjects(orig, msg2); XCTAssertEqualObjects(orig, msg2);

@ -5,16 +5,18 @@
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h"
#import <objc/runtime.h> #import <objc/runtime.h>
#import "GPBArray.h"
#import "GPBArray_PackagePrivate.h" #import "GPBArray_PackagePrivate.h"
#import "GPBDescriptor.h" #import "GPBDescriptor.h"
#import "GPBDictionary_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h"
#import "GPBMessage_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownField_PackagePrivate.h"
#import "GPBUnknownFields.h"
#import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h"
#import "objectivec/Tests/UnittestImport.pbobjc.h" #import "objectivec/Tests/UnittestImport.pbobjc.h"
#import "objectivec/Tests/UnittestObjc.pbobjc.h" #import "objectivec/Tests/UnittestObjc.pbobjc.h"
@ -501,6 +503,11 @@
[message setUnknownFields:unknownFields]; [message setUnknownFields:unknownFields];
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 fixed32:1234];
[ufs addFieldNumber:2345 varint:54321];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSString *description = [message description]; NSString *description = [message description];
XCTAssertGreaterThan([description length], 0U); XCTAssertGreaterThan([description length], 0U);
@ -985,6 +992,19 @@
XCTAssertFalse([message hasOptionalNestedMessage]); XCTAssertFalse([message hasOptionalNestedMessage]);
[message.optionalNestedMessage setUnknownFields:unknownFields]; [message.optionalNestedMessage setUnknownFields:unknownFields];
XCTAssertTrue([message hasOptionalNestedMessage]); XCTAssertTrue([message hasOptionalNestedMessage]);
message.optionalNestedMessage = nil;
XCTAssertFalse([message hasOptionalNestedMessage]);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1 varint:1];
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message hasOptionalNestedMessage]);
message.optionalNestedMessage = nil;
XCTAssertFalse([message hasOptionalNestedMessage]);
[ufs clear]; // Also make sure merging zero length forces it to become visible.
[message.optionalNestedMessage mergeUnknownFields:ufs extensionRegistry:nil];
XCTAssertTrue([message hasOptionalNestedMessage]);
} }
- (void)testSetAutocreatedSubmessageToSelf { - (void)testSetAutocreatedSubmessageToSelf {
@ -1481,6 +1501,19 @@
XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]); XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]);
XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]); XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertEqual(ufs.count, 3);
uint64_t varint;
XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 10);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 11);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 12);
GPBUnknownFieldSet *unknownFields = msg.unknownFields; GPBUnknownFieldSet *unknownFields = msg.unknownFields;
GPBUnknownField *field = GPBUnknownField *field =
[unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber]; [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
@ -1523,6 +1556,18 @@
expected = @[ @4, @6 ]; expected = @[ @4, @6 ];
XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedForeignEnumExtension]], expected); XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedForeignEnumExtension]], expected);
ufs = [[[GPBUnknownFields alloc] initFromMessage:msg] autorelease];
XCTAssertEqual(ufs.count, 3);
XCTAssertTrue([ufs getFirst:[UnittestRoot optionalNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 10);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedNestedEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 11);
XCTAssertTrue([ufs getFirst:[UnittestRoot repeatedForeignEnumExtension].fieldNumber
varint:&varint]);
XCTAssertEqual(varint, 12);
unknownFields = msg.unknownFields; unknownFields = msg.unknownFields;
field = [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber]; field = [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
XCTAssertNotNil(field); XCTAssertNotNil(field);
@ -1840,6 +1885,9 @@
[unknowns mergeVarintField:123 value:456]; [unknowns mergeVarintField:123 value:456];
GPBMessage *message = [GPBMessage message]; GPBMessage *message = [GPBMessage message];
[message setUnknownFields:unknowns]; [message setUnknownFields:unknowns];
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:1234 varint:5678];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSData *data = [message data]; NSData *data = [message data];
GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL]; GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
XCTAssertEqualObjects(message, message2); XCTAssertEqualObjects(message, message2);
@ -1850,12 +1898,19 @@
[unknowns1 mergeVarintField:123 value:456]; [unknowns1 mergeVarintField:123 value:456];
GPBMessage *message1 = [GPBMessage message]; GPBMessage *message1 = [GPBMessage message];
[message1 setUnknownFields:unknowns1]; [message1 setUnknownFields:unknowns1];
GPBUnknownFields *ufs1 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs1 addFieldNumber:1234 varint:5678];
[message1 mergeUnknownFields:ufs1 extensionRegistry:nil];
GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
[unknowns2 mergeVarintField:789 value:987]; [unknowns2 mergeVarintField:789 value:987];
[unknowns2 mergeVarintField:654 value:321]; [unknowns2 mergeVarintField:654 value:321];
GPBMessage *message2 = [GPBMessage message]; GPBMessage *message2 = [GPBMessage message];
[message2 setUnknownFields:unknowns2]; [message2 setUnknownFields:unknowns2];
GPBUnknownFields *ufs2 = [[[GPBUnknownFields alloc] init] autorelease];
[ufs2 addFieldNumber:2345 fixed32:6789];
[ufs2 addFieldNumber:3456 fixed32:7890];
[message2 mergeUnknownFields:ufs2 extensionRegistry:nil];
NSMutableData *delimitedData = [NSMutableData data]; NSMutableData *delimitedData = [NSMutableData data];
[delimitedData appendData:[message1 delimitedData]]; [delimitedData appendData:[message1 delimitedData]];
@ -2022,6 +2077,54 @@
XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
} }
- (void)testCloseEnumsValuesOutOfRange {
// The unknown values should all make it into the unknown fields.
EnumTestMsg *msg1 = [EnumTestMsg message];
msg1.bar = EnumTestMsg_MyEnum_NegTwo;
msg1.baz = EnumTestMsg_MyEnum_Two;
[msg1.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
[msg1.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo];
NSData *data = [msg1 data];
XCTAssertNotNil(data);
EnumTestMsgPrime *msg2 = [EnumTestMsgPrime parseFromData:data error:NULL];
XCTAssertNotNil(msg2);
XCTAssertEqualObjects(data, [msg2 data]);
XCTAssertFalse(msg2.hasBar);
XCTAssertFalse(msg2.hasBaz);
XCTAssertEqual(msg2.mumbleArray_Count, 0U);
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] initFromMessage:msg2] autorelease];
XCTAssertEqual(ufs.count, 4U);
uint64_t varint;
XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Bar varint:&varint]);
XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo);
XCTAssertTrue([ufs getFirst:EnumTestMsg_FieldNumber_Baz varint:&varint]);
XCTAssertEqual(varint, (uint64_t)EnumTestMsg_MyEnum_Two);
NSArray<GPBUnknownField *> *fields = [ufs fields:EnumTestMsg_FieldNumber_MumbleArray];
XCTAssertEqual(fields.count, 2U);
XCTAssertEqual(fields[0].varint, (uint64_t)EnumTestMsg_MyEnum_Two);
XCTAssertEqual(fields[1].varint, (uint64_t)EnumTestMsg_MyEnum_NegTwo);
GPBUnknownFieldSet *unknownFields = msg2.unknownFields;
XCTAssertNotNil(unknownFields);
XCTAssertEqual(unknownFields.countOfFields, 3U);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Bar]);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_Baz]);
XCTAssertTrue([unknownFields hasField:EnumTestMsg_FieldNumber_MumbleArray]);
GPBUnknownField *field = [unknownFields getField:EnumTestMsg_FieldNumber_Bar];
XCTAssertEqual(field.varintList.count, 1U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_NegTwo);
field = [unknownFields getField:EnumTestMsg_FieldNumber_Baz];
XCTAssertEqual(field.varintList.count, 1U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two);
field = [unknownFields getField:EnumTestMsg_FieldNumber_MumbleArray];
XCTAssertEqual(field.varintList.count, 2U);
XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)EnumTestMsg_MyEnum_Two);
XCTAssertEqual([field.varintList valueAtIndex:1], (uint64_t)EnumTestMsg_MyEnum_NegTwo);
}
- (void)testReservedWordNaming { - (void)testReservedWordNaming {
// names.cc has some special handing to make sure that some "reserved" objc // names.cc has some special handing to make sure that some "reserved" objc
// names get renamed in a way so they don't conflict. // names get renamed in a way so they don't conflict.

@ -6,6 +6,7 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#import "GPBTestUtilities.h" #import "GPBTestUtilities.h"
#import "GPBUnknownFieldSet.h"
#import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h"
#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownField_PackagePrivate.h"
@ -281,6 +282,10 @@
TestEmptyMessage* destination2 = [TestEmptyMessage message]; TestEmptyMessage* destination2 = [TestEmptyMessage message];
[destination2 mergeFrom:source3]; [destination2 mergeFrom:source3];
XCTAssertEqualObjects(destination1.unknownFields, destination2.unknownFields);
XCTAssertEqualObjects(destination1.unknownFields, source3.unknownFields);
XCTAssertEqualObjects(destination2.unknownFields, source3.unknownFields);
XCTAssertEqualObjects(destination1.data, destination2.data); XCTAssertEqualObjects(destination1.data, destination2.data);
XCTAssertEqualObjects(destination1.data, source3.data); XCTAssertEqualObjects(destination1.data, source3.data);
XCTAssertEqualObjects(destination2.data, source3.data); XCTAssertEqualObjects(destination2.data, source3.data);
@ -376,6 +381,180 @@
XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]); XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
} }
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
GPBUnknownField* field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
GPBUnknownFieldSet* group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:2];
XCTAssertEqual(field.fixed32List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed32List valueAtIndex:0], 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:3];
XCTAssertEqual(field.fixed64List.count, (NSUInteger)1);
XCTAssertEqual([field.fixed64List valueAtIndex:0], 0x123456789abcdef0LL);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:6];
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)1);
XCTAssertEqualObjects(field.lengthDelimitedList[0], DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)0);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)2);
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 1);
field = [group getField:5];
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
field = [group getField:1];
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
XCTAssertEqual(m.unknownFields.countOfFields, (NSUInteger)1);
field = [m.unknownFields getField:4];
for (NSUInteger i = 0; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(field.varintList.count, (NSUInteger)0);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)1);
group = field.groupList[0];
XCTAssertEqual(group.countOfFields, (NSUInteger)1);
field = [group getField:(i < (kDefaultRecursionLimit - 1) ? 4 : 1)];
}
// field is of the inner most group
XCTAssertEqual(field.varintList.count, (NSUInteger)1);
XCTAssertEqual([field.varintList valueAtIndex:0], (NSUInteger)1);
XCTAssertEqual(field.fixed32List.count, (NSUInteger)0);
XCTAssertEqual(field.fixed64List.count, (NSUInteger)0);
XCTAssertEqual(field.lengthDelimitedList.count, (NSUInteger)0);
XCTAssertEqual(field.groupList.count, (NSUInteger)0);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
#pragma mark - Field tests #pragma mark - Field tests
// Some tests directly on fields since the dictionary in FieldSet can gate // Some tests directly on fields since the dictionary in FieldSet can gate
// testing some of these. // testing some of these.

@ -847,4 +847,163 @@
XCTAssertEqual(varint, 0x7FFFFFFFFFFFFFFFL); XCTAssertEqual(varint, 0x7FFFFFFFFFFFFFFFL);
} }
static NSData* DataForGroupsOfDepth(NSUInteger depth) {
NSMutableData* data = [NSMutableData dataWithCapacity:0];
uint32_t byte = 35; // 35 = 0b100011 -> field 4/start group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
byte = 8; // 8 = 0b1000, -> field 1/varint
[data appendBytes:&byte length:1];
byte = 1; // 1 -> varint value of 1
[data appendBytes:&byte length:1];
byte = 36; // 36 = 0b100100 -> field 4/end group
for (NSUInteger i = 0; i < depth; ++i) {
[data appendBytes:&byte length:1];
}
return data;
}
- (void)testParsingNestingGroupData {
// 35 = 0b100011 -> field 4/start group
// 36 = 0b100100 -> field 4/end group
// 43 = 0b101011 -> field 5/end group
// 44 = 0b101100 -> field 5/end group
// 8 = 0b1000, 1 -> field 1/varint, value of 1
// 21 = 0b10101, 0x78, 0x56, 0x34, 0x12 -> field 2/fixed32, value of 0x12345678
// 25 = 0b11001, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12 -> field 3/fixed64,
// value of 0x123456789abcdef0LL
// 50 = 0b110010, 0x0 -> field 6/length delimited, length 0
// 50 = 0b110010, 0x1, 42 -> field 6/length delimited, length 1, byte 42
// 0 -> field 0 which is invalid/varint
// 15 = 0b1111 -> field 1, wire type 7 which is invalid
TestEmptyMessage* m = [TestEmptyMessage parseFromData:DataFromBytes(35, 36)
error:NULL]; // empty group
GPBUnknownFields* ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
GPBUnknownFields* group = [ufs firstGroup:4];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 36) error:NULL]; // varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34, 0x12, 36)
error:NULL]; // fixed32
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint32_t fixed32 = 0;
XCTAssertTrue([group getFirst:2 fixed32:&fixed32]);
XCTAssertEqual(fixed32, 0x12345678);
m = [TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12,
36)
error:NULL]; // fixed64
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
uint64_t fixed64 = 0;
XCTAssertTrue([group getFirst:3 fixed64:&fixed64]);
XCTAssertEqual(fixed64, 0x123456789abcdef0LL);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 0, 36)
error:NULL]; // length delimited, length 0
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
NSData* lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, [NSData data]);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 50, 1, 42, 36)
error:NULL]; // length delimited, length 1, byte 42
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
lengthDelimited = [group firstLengthDelimited:6];
XCTAssertEqualObjects(lengthDelimited, DataFromBytes(42));
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 36) error:NULL]; // Sub group
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:5];
XCTAssertTrue(group.empty);
m = [TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 43, 8, 2, 44, 36)
error:NULL]; // varint and sub group with varint
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
XCTAssertEqual(group.count, (NSUInteger)2);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
group = [group firstGroup:5];
XCTAssertEqual(group.count, (NSUInteger)1);
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 2);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 0, 36)
error:NULL]); // Invalid field number
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 15, 36)
error:NULL]); // Invalid wire type
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 21, 0x78, 0x56, 0x34)
error:NULL]); // truncated fixed32
XCTAssertNil([TestEmptyMessage
parseFromData:DataFromBytes(35, 25, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
0x34)
error:NULL]); // truncated fixed64
// Mising end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1) error:NULL]);
// Wrong end group
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 8, 1, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 36) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 44, 44) error:NULL]);
XCTAssertNil([TestEmptyMessage parseFromData:DataFromBytes(35, 43, 8, 1, 44, 44) error:NULL]);
// This is the same limit as within GPBCodedInputStream.
const NSUInteger kDefaultRecursionLimit = 100;
// That depth parses.
NSData* testData = DataForGroupsOfDepth(kDefaultRecursionLimit);
m = [TestEmptyMessage parseFromData:testData error:NULL];
ufs = [[[GPBUnknownFields alloc] initFromMessage:m] autorelease];
XCTAssertEqual(ufs.count, (NSUInteger)1);
group = [ufs firstGroup:4];
for (NSUInteger i = 1; i < kDefaultRecursionLimit; ++i) {
XCTAssertEqual(group.count, (NSUInteger)1);
group = [group firstGroup:4];
}
// group is now the inner most group.
XCTAssertEqual(group.count, (NSUInteger)1);
varint = 0;
XCTAssertTrue([group getFirst:1 varint:&varint]);
XCTAssertEqual(varint, 1);
// One more level deep fails.
testData = DataForGroupsOfDepth(kDefaultRecursionLimit + 1);
XCTAssertNil([TestEmptyMessage parseFromData:testData error:NULL]);
}
@end @end

@ -6,17 +6,16 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#import <XCTest/XCTest.h> #import <XCTest/XCTest.h>
#import "GPBUtilities_PackagePrivate.h"
#import <objc/runtime.h> #import <objc/runtime.h>
#import "GPBTestUtilities.h"
#import "GPBDescriptor.h" #import "GPBDescriptor.h"
#import "GPBDescriptor_PackagePrivate.h" #import "GPBDescriptor_PackagePrivate.h"
#import "GPBMessage.h" #import "GPBMessage.h"
#import "GPBTestUtilities.h"
#import "GPBUnknownField.h"
#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownField_PackagePrivate.h"
#import "GPBUtilities.h"
#import "GPBUtilities_PackagePrivate.h"
#import "objectivec/Tests/MapUnittest.pbobjc.h" #import "objectivec/Tests/MapUnittest.pbobjc.h"
#import "objectivec/Tests/Unittest.pbobjc.h" #import "objectivec/Tests/Unittest.pbobjc.h"
@ -168,6 +167,54 @@
[expected release]; [expected release];
} }
- (void)testTextFormatUnknownFields {
GPBUnknownFields *ufs = [[[GPBUnknownFields alloc] init] autorelease];
[ufs addFieldNumber:100 varint:5];
[ufs addFieldNumber:100 varint:4];
[ufs addFieldNumber:10 varint:1];
[ufs addFieldNumber:300 fixed32:0x50];
[ufs addFieldNumber:300 fixed32:0x40];
[ufs addFieldNumber:10 fixed32:0x10];
[ufs addFieldNumber:200 fixed64:0x5000];
[ufs addFieldNumber:200 fixed64:0x4000];
[ufs addFieldNumber:10 fixed64:0x1000];
[ufs addFieldNumber:10 lengthDelimited:DataFromCStr("foo")];
[ufs addFieldNumber:10 lengthDelimited:DataFromCStr("bar")];
GPBUnknownFields *group = [ufs addGroupWithFieldNumber:150];
[group addFieldNumber:2 varint:2];
[group addFieldNumber:1 varint:1];
group = [ufs addGroupWithFieldNumber:150];
[group addFieldNumber:1 varint:1];
[group addFieldNumber:3 fixed32:0x3];
[group addFieldNumber:2 fixed64:0x2];
TestEmptyMessage *message = [TestEmptyMessage message];
[message mergeUnknownFields:ufs extensionRegistry:nil];
NSString *expected = @"# --- Unknown fields ---\n"
@"10: 1\n"
@"10: 0x10\n"
@"10: 0x1000\n"
@"10: \"foo\"\n"
@"10: \"bar\"\n"
@"100: 5\n"
@"100: 4\n"
@"150: {\n"
@" 1: 1\n"
@" 2: 2\n"
@"}\n"
@"150: {\n"
@" 1: 1\n"
@" 2: 0x2\n"
@" 3: 0x3\n"
@"}\n"
@"200: 0x5000\n"
@"200: 0x4000\n"
@"300: 0x50\n"
@"300: 0x40\n";
NSString *result = GPBTextFormatForMessage(message, nil);
XCTAssertEqualObjects(expected, result);
}
- (void)testSetRepeatedFields { - (void)testSetRepeatedFields {
TestAllTypes *message = [TestAllTypes message]; TestAllTypes *message = [TestAllTypes message];
@ -204,11 +251,27 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
return result; return result;
} }
// Helper to add an unknown field data to messages.
static void AddUnknownFields(GPBMessage *message, int num) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] init];
[ufs addFieldNumber:num varint:num];
[message mergeUnknownFields:ufs extensionRegistry:nil];
[ufs release];
}
static BOOL HasUnknownFields(GPBMessage *message) {
GPBUnknownFields *ufs = [[GPBUnknownFields alloc] initFromMessage:message];
BOOL result = !ufs.empty;
[ufs release];
return result;
}
- (void)testDropMessageUnknownFieldsRecursively { - (void)testDropMessageUnknownFieldsRecursively {
TestAllExtensions *message = [TestAllExtensions message]; TestAllExtensions *message = [TestAllExtensions message];
// Give it unknownFields. // Give it unknownFields.
message.unknownFields = UnknownFieldsSetHelper(777); message.unknownFields = UnknownFieldsSetHelper(777);
AddUnknownFields(message, 1777);
// Given it extensions that include a message with unknown fields of its own. // Given it extensions that include a message with unknown fields of its own.
{ {
@ -219,18 +282,21 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message]; OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
optionalGroup.a = 123; optionalGroup.a = 123;
optionalGroup.unknownFields = UnknownFieldsSetHelper(779); optionalGroup.unknownFields = UnknownFieldsSetHelper(779);
AddUnknownFields(optionalGroup, 1779);
[message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup]; [message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup];
// Message // Message
TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message]; TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
nestedMessage.bb = 456; nestedMessage.bb = 456;
nestedMessage.unknownFields = UnknownFieldsSetHelper(778); nestedMessage.unknownFields = UnknownFieldsSetHelper(778);
AddUnknownFields(nestedMessage, 1778);
[message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage]; [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
// Repeated Group // Repeated Group
RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init]; RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init];
repeatedGroup.a = 567; repeatedGroup.a = 567;
repeatedGroup.unknownFields = UnknownFieldsSetHelper(780); repeatedGroup.unknownFields = UnknownFieldsSetHelper(780);
AddUnknownFields(repeatedGroup, 1780);
[message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup]; [message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup];
[repeatedGroup release]; [repeatedGroup release];
@ -238,6 +304,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
nestedMessage = [[TestAllTypes_NestedMessage alloc] init]; nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
nestedMessage.bb = 678; nestedMessage.bb = 678;
nestedMessage.unknownFields = UnknownFieldsSetHelper(781); nestedMessage.unknownFields = UnknownFieldsSetHelper(781);
AddUnknownFields(nestedMessage, 1781);
[message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage]; [message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage];
[nestedMessage release]; [nestedMessage release];
} }
@ -245,6 +312,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
// Confirm everything is there. // Confirm everything is there.
XCTAssertNotNil(message); XCTAssertNotNil(message);
XCTAssertTrue(HasUnknownFields(message));
XCTAssertNotNil(message.unknownFields); XCTAssertNotNil(message.unknownFields);
XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
@ -254,6 +322,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalGroupExtension]]; [message getExtension:[UnittestRoot optionalGroupExtension]];
XCTAssertNotNil(optionalGroup); XCTAssertNotNil(optionalGroup);
XCTAssertEqual(optionalGroup.a, 123); XCTAssertEqual(optionalGroup.a, 123);
XCTAssertTrue(HasUnknownFields(optionalGroup));
XCTAssertNotNil(optionalGroup.unknownFields); XCTAssertNotNil(optionalGroup.unknownFields);
} }
@ -263,6 +332,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalNestedMessageExtension]]; [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
XCTAssertNotNil(nestedMessage); XCTAssertNotNil(nestedMessage);
XCTAssertEqual(nestedMessage.bb, 456); XCTAssertEqual(nestedMessage.bb, 456);
XCTAssertTrue(HasUnknownFields(nestedMessage));
XCTAssertNotNil(nestedMessage.unknownFields); XCTAssertNotNil(nestedMessage.unknownFields);
} }
@ -273,6 +343,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
XCTAssertNotNil(repeatedGroup); XCTAssertNotNil(repeatedGroup);
XCTAssertEqual(repeatedGroup.a, 567); XCTAssertEqual(repeatedGroup.a, 567);
XCTAssertTrue(HasUnknownFields(repeatedGroup));
XCTAssertNotNil(repeatedGroup.unknownFields); XCTAssertNotNil(repeatedGroup.unknownFields);
} }
@ -284,6 +355,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
XCTAssertNotNil(repeatedNestedMessage); XCTAssertNotNil(repeatedNestedMessage);
XCTAssertEqual(repeatedNestedMessage.bb, 678); XCTAssertEqual(repeatedNestedMessage.bb, 678);
XCTAssertTrue(HasUnknownFields(repeatedNestedMessage));
XCTAssertNotNil(repeatedNestedMessage.unknownFields); XCTAssertNotNil(repeatedNestedMessage.unknownFields);
} }
@ -293,6 +365,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
// Confirm unknowns are gone from within the messages. // Confirm unknowns are gone from within the messages.
XCTAssertNotNil(message); XCTAssertNotNil(message);
XCTAssertFalse(HasUnknownFields(message));
XCTAssertNil(message.unknownFields); XCTAssertNil(message.unknownFields);
XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]); XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
@ -302,6 +375,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalGroupExtension]]; [message getExtension:[UnittestRoot optionalGroupExtension]];
XCTAssertNotNil(optionalGroup); XCTAssertNotNil(optionalGroup);
XCTAssertEqual(optionalGroup.a, 123); XCTAssertEqual(optionalGroup.a, 123);
XCTAssertFalse(HasUnknownFields(optionalGroup));
XCTAssertNil(optionalGroup.unknownFields); XCTAssertNil(optionalGroup.unknownFields);
} }
@ -311,6 +385,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
[message getExtension:[UnittestRoot optionalNestedMessageExtension]]; [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
XCTAssertNotNil(nestedMessage); XCTAssertNotNil(nestedMessage);
XCTAssertEqual(nestedMessage.bb, 456); XCTAssertEqual(nestedMessage.bb, 456);
XCTAssertFalse(HasUnknownFields(nestedMessage));
XCTAssertNil(nestedMessage.unknownFields); XCTAssertNil(nestedMessage.unknownFields);
} }
@ -321,6 +396,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject; RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
XCTAssertNotNil(repeatedGroup); XCTAssertNotNil(repeatedGroup);
XCTAssertEqual(repeatedGroup.a, 567); XCTAssertEqual(repeatedGroup.a, 567);
XCTAssertFalse(HasUnknownFields(repeatedGroup));
XCTAssertNil(repeatedGroup.unknownFields); XCTAssertNil(repeatedGroup.unknownFields);
} }
@ -332,6 +408,7 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject; TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
XCTAssertNotNil(repeatedNestedMessage); XCTAssertNotNil(repeatedNestedMessage);
XCTAssertEqual(repeatedNestedMessage.bb, 678); XCTAssertEqual(repeatedNestedMessage.bb, 678);
XCTAssertFalse(HasUnknownFields(repeatedNestedMessage));
XCTAssertNil(repeatedNestedMessage.unknownFields); XCTAssertNil(repeatedNestedMessage.unknownFields);
} }
} }
@ -342,10 +419,12 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{ {
ForeignMessage *foreignMessage = [ForeignMessage message]; ForeignMessage *foreignMessage = [ForeignMessage message];
foreignMessage.unknownFields = UnknownFieldsSetHelper(100); foreignMessage.unknownFields = UnknownFieldsSetHelper(100);
AddUnknownFields(foreignMessage, 1000);
[message.mapInt32ForeignMessage setObject:foreignMessage forKey:100]; [message.mapInt32ForeignMessage setObject:foreignMessage forKey:100];
foreignMessage = [ForeignMessage message]; foreignMessage = [ForeignMessage message];
foreignMessage.unknownFields = UnknownFieldsSetHelper(101); foreignMessage.unknownFields = UnknownFieldsSetHelper(101);
AddUnknownFields(foreignMessage, 1001);
[message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"]; [message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"];
} }
@ -356,12 +435,14 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{ {
ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
XCTAssertNotNil(foreignMessage); XCTAssertNotNil(foreignMessage);
XCTAssertTrue(HasUnknownFields(foreignMessage));
XCTAssertNotNil(foreignMessage.unknownFields); XCTAssertNotNil(foreignMessage.unknownFields);
} }
{ {
ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
XCTAssertNotNil(foreignMessage); XCTAssertNotNil(foreignMessage);
XCTAssertTrue(HasUnknownFields(foreignMessage));
XCTAssertNotNil(foreignMessage.unknownFields); XCTAssertNotNil(foreignMessage.unknownFields);
} }
@ -374,12 +455,14 @@ static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
{ {
ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100]; ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
XCTAssertNotNil(foreignMessage); XCTAssertNotNil(foreignMessage);
XCTAssertFalse(HasUnknownFields(foreignMessage));
XCTAssertNil(foreignMessage.unknownFields); XCTAssertNil(foreignMessage.unknownFields);
} }
{ {
ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"]; ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
XCTAssertNotNil(foreignMessage); XCTAssertNotNil(foreignMessage);
XCTAssertFalse(HasUnknownFields(foreignMessage));
XCTAssertNil(foreignMessage.unknownFields); XCTAssertNil(foreignMessage.unknownFields);
} }
} }

@ -7,11 +7,11 @@
syntax = "proto2"; syntax = "proto2";
package objc.protobuf.tests;
import "google/protobuf/any.proto"; import "google/protobuf/any.proto";
import "objectivec/Tests/unittest.proto"; import "objectivec/Tests/unittest.proto";
package objc.protobuf.tests;
// Explicit empty prefix, tests some validations code paths also. // Explicit empty prefix, tests some validations code paths also.
option objc_class_prefix = ""; option objc_class_prefix = "";
@ -167,7 +167,6 @@ message self {
} }
extensions 3000 to 3999; extensions 3000 to 3999;
} }
enum retain { enum retain {
@ -700,13 +699,17 @@ message JustToScopeExtensions {
repeated string mutableCopy_val_lower_complex_repeated = 2711; repeated string mutableCopy_val_lower_complex_repeated = 2711;
repeated string mutableCopy_Val_upper_complex_repeated = 2712; repeated string mutableCopy_Val_upper_complex_repeated = 2712;
repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 2713; repeated string mutableCopyvalue_lower_no_underscore_complex_repeated =
repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 2714; 2713;
repeated string mutableCopyValue_upper_no_underscore_complex_repeated =
2714;
repeated int32 mutableCopy_val_lower_primitive_repeated = 2715; repeated int32 mutableCopy_val_lower_primitive_repeated = 2715;
repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716; repeated int32 mutableCopy_Val_upper_primitive_repeated = 2716;
repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 2717; repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated =
repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 2718; 2717;
repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated =
2718;
repeated self mutableCopy_val_lower_message_repeated = 2719; repeated self mutableCopy_val_lower_message_repeated = 2719;
repeated self mutableCopy_Val_upper_message_repeated = 2720; repeated self mutableCopy_Val_upper_message_repeated = 2720;
@ -794,6 +797,20 @@ message EnumTestMsg {
repeated MyEnum mumble = 4; repeated MyEnum mumble = 4;
} }
message EnumTestMsgPrime {
enum MyEnumPrime {
ZERO = 0;
ONE = 1;
NEG_ONE = -1;
// Lacks 2, -2.
}
optional MyEnumPrime foo = 1;
optional MyEnumPrime bar = 2 [default = ONE];
optional MyEnumPrime baz = 3 [default = NEG_ONE];
repeated MyEnumPrime mumble = 4;
}
// Test case for https://github.com/protocolbuffers/protobuf/issues/1453 // Test case for https://github.com/protocolbuffers/protobuf/issues/1453
// Message with no explicit defaults, but a non zero default for an enum. // Message with no explicit defaults, but a non zero default for an enum.
message MessageWithOneBasedEnum { message MessageWithOneBasedEnum {

@ -51,11 +51,11 @@ def protobuf_deps():
if not native.existing_rule("bazel_skylib"): if not native.existing_rule("bazel_skylib"):
http_archive( http_archive(
name = "bazel_skylib", name = "bazel_skylib",
sha256 = "d00f1389ee20b60018e92644e0948e16e350a7707219e7a390fb0a99b6ec9262",
urls = [ urls = [
"https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz",
"https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz", "https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.0/bazel-skylib-1.7.0.tar.gz",
], ],
sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
) )
if not native.existing_rule("com_google_absl"): if not native.existing_rule("com_google_absl"):
@ -84,8 +84,8 @@ def protobuf_deps():
_github_archive( _github_archive(
name = "jsoncpp", name = "jsoncpp",
repo = "https://github.com/open-source-parsers/jsoncpp", repo = "https://github.com/open-source-parsers/jsoncpp",
commit = "9059f5cad030ba11d37818847443a53918c327b1", # 1.9.4 commit = "5defb4ed1a4293b8e2bf641e16b156fb9de498cc", # 1.9.5
sha256 = "c0c583c7b53a53bcd1f7385f15439dcdf0314d550362379e2db9919a918d1996", sha256 = "a03d3136ff6dd092143bba8d3ded641e87b44e6c0b1f632b368f6cc8587524b5",
build_file = Label("//:third_party/jsoncpp.BUILD"), build_file = Label("//:third_party/jsoncpp.BUILD"),
) )
@ -120,17 +120,6 @@ def protobuf_deps():
sha256 = "160d1ebf33763124766fb35316329d907ca67f733238aa47624a8e3ff3cf2ef4", sha256 = "160d1ebf33763124766fb35316329d907ca67f733238aa47624a8e3ff3cf2ef4",
) )
# TODO: remove after toolchain types are moved to protobuf
if not native.existing_rule("rules_proto"):
http_archive(
name = "rules_proto",
sha256 = "dc3fb206a2cb3441b485eb1e423165b231235a1ea9b031b4433cf7bc1fa460dd",
strip_prefix = "rules_proto-5.3.0-21.7",
urls = [
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/5.3.0-21.7.tar.gz",
],
)
if not native.existing_rule("proto_bazel_features"): if not native.existing_rule("proto_bazel_features"):
proto_bazel_features(name = "proto_bazel_features") proto_bazel_features(name = "proto_bazel_features")

@ -1,185 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
#include "protos/protos.h"
#include <atomic>
#include <cstddef>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "protos/protos_extension_lock.h"
#include "upb/mem/arena.h"
#include "upb/message/accessors.h"
#include "upb/message/copy.h"
#include "upb/message/message.h"
#include "upb/message/promote.h"
#include "upb/message/value.h"
#include "upb/mini_table/extension.h"
#include "upb/mini_table/extension_registry.h"
#include "upb/mini_table/message.h"
#include "upb/wire/decode.h"
#include "upb/wire/encode.h"
namespace protos {
// begin:google_only
// absl::Status MessageAllocationError(SourceLocation loc) {
// return absl::Status(absl::StatusCode::kInternal,
// "Upb message allocation error", loc);
// }
//
// absl::Status ExtensionNotFoundError(int extension_number, SourceLocation loc) {
// return absl::Status(
// absl::StatusCode::kInternal,
// absl::StrFormat("Extension %d not found", extension_number), loc);
// }
//
// absl::Status MessageEncodeError(upb_EncodeStatus status, SourceLocation loc) {
// return absl::Status(absl::StatusCode::kInternal,
// absl::StrFormat("Upb message encoding error %d", status),
// loc
//
// );
// }
//
// absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc
//
// ) {
// return absl::Status(absl::StatusCode::kInternal,
// absl::StrFormat("Upb message parse error %d", status), loc
//
// );
// }
// end:google_only
// begin:github_only
absl::Status MessageAllocationError(SourceLocation loc) {
return absl::Status(absl::StatusCode::kUnknown,
"Upb message allocation error");
}
absl::Status ExtensionNotFoundError(int ext_number, SourceLocation loc) {
return absl::Status(absl::StatusCode::kUnknown,
absl::StrFormat("Extension %d not found", ext_number));
}
absl::Status MessageEncodeError(upb_EncodeStatus s, SourceLocation loc) {
return absl::Status(absl::StatusCode::kUnknown, "Encoding error");
}
absl::Status MessageDecodeError(upb_DecodeStatus status, SourceLocation loc
) {
return absl::Status(absl::StatusCode::kUnknown, "Upb message parse error");
}
// end:github_only
namespace internal {
upb_ExtensionRegistry* GetUpbExtensions(
const ExtensionRegistry& extension_registry) {
return extension_registry.registry_;
}
/**
* MessageLock(msg) acquires lock on msg when constructed and releases it when
* destroyed.
*/
class MessageLock {
public:
explicit MessageLock(const upb_Message* msg) : msg_(msg) {
UpbExtensionLocker locker =
upb_extension_locker_global.load(std::memory_order_acquire);
unlocker_ = (locker != nullptr) ? locker(msg) : nullptr;
}
MessageLock(const MessageLock&) = delete;
void operator=(const MessageLock&) = delete;
~MessageLock() {
if (unlocker_ != nullptr) {
unlocker_(msg_);
}
}
private:
const upb_Message* msg_;
UpbExtensionUnlocker unlocker_;
};
bool HasExtensionOrUnknown(const upb_Message* msg,
const upb_MiniTableExtension* eid) {
MessageLock msg_lock(msg);
if (upb_Message_HasExtension(msg, eid)) return true;
const int number = upb_MiniTableExtension_Number(eid);
return upb_Message_FindUnknown(msg, number, 0).status == kUpb_FindUnknown_Ok;
}
bool GetOrPromoteExtension(upb_Message* msg, const upb_MiniTableExtension* eid,
upb_Arena* arena, upb_MessageValue* value) {
MessageLock msg_lock(msg);
upb_GetExtension_Status ext_status = upb_Message_GetOrPromoteExtension(
(upb_Message*)msg, eid, 0, arena, value);
return ext_status == kUpb_GetExtension_Ok;
}
absl::StatusOr<absl::string_view> Serialize(const upb_Message* message,
const upb_MiniTable* mini_table,
upb_Arena* arena, int options) {
MessageLock msg_lock(message);
size_t len;
char* ptr;
upb_EncodeStatus status =
upb_Encode(message, mini_table, options, arena, &ptr, &len);
if (status == kUpb_EncodeStatus_Ok) {
return absl::string_view(ptr, len);
}
return MessageEncodeError(status);
}
void DeepCopy(upb_Message* target, const upb_Message* source,
const upb_MiniTable* mini_table, upb_Arena* arena) {
MessageLock msg_lock(source);
upb_Message_DeepCopy(target, source, mini_table, arena);
}
upb_Message* DeepClone(const upb_Message* source,
const upb_MiniTable* mini_table, upb_Arena* arena) {
MessageLock msg_lock(source);
return upb_Message_DeepClone(source, mini_table, arena);
}
absl::Status MoveExtension(upb_Message* message, upb_Arena* message_arena,
const upb_MiniTableExtension* ext,
upb_Message* extension, upb_Arena* extension_arena) {
if (message_arena != extension_arena &&
// Try fuse, if fusing is not allowed or fails, create copy of extension.
!upb_Arena_Fuse(message_arena, extension_arena)) {
extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext),
message_arena);
}
return upb_Message_SetExtension(message, ext, &extension, message_arena)
? absl::OkStatus()
: MessageAllocationError();
}
absl::Status SetExtension(upb_Message* message, upb_Arena* message_arena,
const upb_MiniTableExtension* ext,
const upb_Message* extension) {
// Clone extension into target message arena.
extension = DeepClone(extension, upb_MiniTableExtension_GetSubMessage(ext),
message_arena);
return upb_Message_SetExtension(message, ext, &extension, message_arena)
? absl::OkStatus()
: MessageAllocationError();
}
} // namespace internal
} // namespace protos

@ -4,8 +4,35 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at // license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
#ifndef UPB_PROTOS_PROTOS_H_ #ifndef UPB_PROTOS_PROTOS_H_
#define UPB_PROTOS_PROTOS_H_ #define UPB_PROTOS_PROTOS_H_
#include "google/protobuf/hpb/hpb.h" #include "google/protobuf/hpb/hpb.h"
namespace protos {
namespace internal {
using hpb::internal::CreateMessage;
using hpb::internal::CreateMessageProxy;
using hpb::internal::DeepClone;
using hpb::internal::DeepCopy;
using hpb::internal::ExtensionIdentifier;
using hpb::internal::GetArena;
using hpb::internal::GetInternalMsg;
using hpb::internal::GetMiniTable;
using hpb::internal::GetOrPromoteExtension;
using hpb::internal::GetUpbExtensions;
using hpb::internal::HasExtensionOrUnknown;
using hpb::internal::MoveExtension;
using hpb::internal::PrivateAccess;
using hpb::internal::Serialize;
using hpb::internal::SetExtension;
} // namespace internal
using hpb::ClearMessage;
using hpb::CloneMessage;
using hpb::CreateMessage;
using hpb::DeepCopy;
using hpb::ClearExtension;
using hpb::GetExtension;
using hpb::HasExtension;
using hpb::SetExtension;
} // namespace protos
#endif #endif

@ -1,28 +0,0 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
// Author: jieluo@google.com (Jie Luo)
syntax = "proto2";
package google.protobuf.internal;
import "google/protobuf/any.proto";
message TestAny {
optional google.protobuf.Any value = 1;
optional int32 int_value = 2;
map<string, int32> map_value = 3;
extensions 10 to max;
}
message TestAnyExtension1 {
extend TestAny {
optional TestAnyExtension1 extension1 = 98418603;
}
optional int32 i = 15;
}

@ -51,7 +51,7 @@ static const char kModuleDocstring[] =
"\n" "\n"
"It complements api_implementation.py by setting defaults using compile-time\n" "It complements api_implementation.py by setting defaults using compile-time\n"
"constants defined in C, such that one can set defaults at compilation\n" "constants defined in C, such that one can set defaults at compilation\n"
"(e.g. with blaze flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2)."; "(e.g. with bazel flag --copt=-DPYTHON_PROTO2_CPP_IMPL_V2).";
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
static struct PyModuleDef _module = { static struct PyModuleDef _module = {

@ -525,7 +525,7 @@ class DescriptorPoolTestBase(object):
unittest_import_pb2.DESCRIPTOR.serialized_pb)) unittest_import_pb2.DESCRIPTOR.serialized_pb))
pool.Add(descriptor_pb2.FileDescriptorProto.FromString( pool.Add(descriptor_pb2.FileDescriptorProto.FromString(
unittest_pb2.DESCRIPTOR.serialized_pb)) unittest_pb2.DESCRIPTOR.serialized_pb))
message_class = message_factory.MessageFactory(pool).GetPrototype( message_class = message_factory.GetMessageClass(
pool.FindMessageTypeByName( pool.FindMessageTypeByName(
unittest_pb2.TestAllTypes.DESCRIPTOR.full_name)) unittest_pb2.TestAllTypes.DESCRIPTOR.full_name))
_CheckDefaultValues(message_class()) _CheckDefaultValues(message_class())

@ -65,7 +65,7 @@ class MessageFactoryTest(unittest.TestCase):
result = cls.FromString(reserialized) result = cls.FromString(reserialized)
self.assertEqual(msg, result) self.assertEqual(msg, result)
def testGetPrototype(self): def testGetMessageClass(self):
db = descriptor_database.DescriptorDatabase() db = descriptor_database.DescriptorDatabase()
pool = descriptor_pool.DescriptorPool(db) pool = descriptor_pool.DescriptorPool(db)
db.Add(self.factory_test1_fd) db.Add(self.factory_test1_fd)

@ -352,10 +352,3 @@ message ConflictJsonName {
optional int32 value = 1 [json_name = "old_value"]; optional int32 value = 1 [json_name = "old_value"];
optional int32 new_value = 2 [json_name = "value"]; optional int32 new_value = 2 [json_name = "value"];
} }
message WKTMessage {
optional Timestamp optional_timestamp = 1;
optional Duration optional_duration = 2;
optional Struct optional_struct = 3;
optional ListValue optional_list_value = 4;
}

@ -72,7 +72,7 @@ class GeneratedProtocolMessageType(type):
mydescriptor = Descriptor(.....) mydescriptor = Descriptor(.....)
factory = symbol_database.Default() factory = symbol_database.Default()
factory.pool.AddDescriptor(mydescriptor) factory.pool.AddDescriptor(mydescriptor)
MyProtoClass = factory.GetPrototype(mydescriptor) MyProtoClass = message_factory.GetMessageClass(mydescriptor)
myproto_instance = MyProtoClass() myproto_instance = MyProtoClass()
myproto.foo_field = 23 myproto.foo_field = 23
... ...
@ -120,7 +120,7 @@ class GeneratedProtocolMessageType(type):
# to achieve similar results. # to achieve similar results.
# #
# This most commonly happens in `text_format.py` when using descriptors from # This most commonly happens in `text_format.py` when using descriptors from
# a custom pool; it calls symbol_database.Global().getPrototype() on a # a custom pool; it calls message_factory.GetMessageClass() on a
# descriptor which already has an existing concrete class. # descriptor which already has an existing concrete class.
new_class = getattr(descriptor, '_concrete_class', None) new_class = getattr(descriptor, '_concrete_class', None)
if new_class: if new_class:
@ -988,7 +988,10 @@ def _InternalUnpackAny(msg):
if descriptor is None: if descriptor is None:
return None return None
message_class = factory.GetPrototype(descriptor) # Unable to import message_factory at top becaue of circular import.
# pylint: disable=g-import-not-at-top
from google.protobuf import message_factory
message_class = message_factory.GetMessageClass(descriptor)
message = message_class() message = message_class()
message.ParseFromString(msg.value) message.ParseFromString(msg.value)

@ -35,11 +35,6 @@ class SymbolDatabaseTest(unittest.TestCase):
db.RegisterServiceDescriptor(unittest_pb2._TESTSERVICE) db.RegisterServiceDescriptor(unittest_pb2._TESTSERVICE)
return db return db
def testGetPrototype(self):
instance = self._Database().GetPrototype(
unittest_pb2.TestAllTypes.DESCRIPTOR)
self.assertTrue(instance is unittest_pb2.TestAllTypes)
def testGetMessages(self): def testGetMessages(self):
messages = self._Database().GetMessages( messages = self._Database().GetMessages(
['google/protobuf/unittest.proto']) ['google/protobuf/unittest.proto'])

@ -19,7 +19,7 @@ import unittest
from google.protobuf import any_pb2 from google.protobuf import any_pb2
from google.protobuf import struct_pb2 from google.protobuf import struct_pb2
from google.protobuf import descriptor_pb2 from google.protobuf import descriptor_pb2
from google.protobuf.internal import any_test_pb2 as test_extend_any from google.protobuf.internal import well_known_types_test_pb2 as test_extend_any
from google.protobuf.internal import api_implementation from google.protobuf.internal import api_implementation
from google.protobuf.internal import message_set_extensions_pb2 from google.protobuf.internal import message_set_extensions_pb2
from google.protobuf.internal import test_proto3_optional_pb2 from google.protobuf.internal import test_proto3_optional_pb2

@ -0,0 +1,29 @@
edition = "2023";
package google.protobuf.internal;
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
message TestAny {
google.protobuf.Any value = 1;
int32 int_value = 2;
map<string, int32> map_value = 3;
extensions 10 to max;
}
message TestAnyExtension1 {
extend TestAny {
TestAnyExtension1 extension1 = 98418603;
}
int32 i = 15;
}
message WKTMessage {
Timestamp optional_timestamp = 1;
Duration optional_duration = 2;
Struct optional_struct = 3;
ListValue optional_list_value = 4;
}

@ -14,9 +14,9 @@ import datetime
import unittest import unittest
from google.protobuf import text_format from google.protobuf import text_format
from google.protobuf.internal import any_test_pb2
from google.protobuf.internal import more_messages_pb2 from google.protobuf.internal import more_messages_pb2
from google.protobuf.internal import well_known_types from google.protobuf.internal import well_known_types
from google.protobuf.internal import well_known_types_test_pb2
from google.protobuf import any_pb2 from google.protobuf import any_pb2
from google.protobuf import duration_pb2 from google.protobuf import duration_pb2
@ -361,7 +361,7 @@ class TimeUtilTest(TimeUtilTestBase):
) )
def testTimestampAssignment(self, date_parts, tzinfo): def testTimestampAssignment(self, date_parts, tzinfo):
original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_timestamp = original_datetime msg.optional_timestamp = original_datetime
self.assertEqual(7200, msg.optional_timestamp.seconds) self.assertEqual(7200, msg.optional_timestamp.seconds)
self.assertEqual(0, msg.optional_timestamp.nanos) self.assertEqual(0, msg.optional_timestamp.nanos)
@ -374,11 +374,13 @@ class TimeUtilTest(TimeUtilTestBase):
) )
def testTimestampCreation(self, date_parts, tzinfo): def testTimestampCreation(self, date_parts, tzinfo):
original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime original_datetime = datetime.datetime(*date_parts, tzinfo=tzinfo) # pylint:disable=g-tzinfo-datetime
msg = more_messages_pb2.WKTMessage(optional_timestamp=original_datetime) msg = well_known_types_test_pb2.WKTMessage(
optional_timestamp=original_datetime
)
self.assertEqual(7200, msg.optional_timestamp.seconds) self.assertEqual(7200, msg.optional_timestamp.seconds)
self.assertEqual(0, msg.optional_timestamp.nanos) self.assertEqual(0, msg.optional_timestamp.nanos)
msg2 = more_messages_pb2.WKTMessage( msg2 = well_known_types_test_pb2.WKTMessage(
optional_timestamp=msg.optional_timestamp optional_timestamp=msg.optional_timestamp
) )
self.assertEqual(7200, msg2.optional_timestamp.seconds) self.assertEqual(7200, msg2.optional_timestamp.seconds)
@ -401,24 +403,24 @@ class TimeUtilTest(TimeUtilTestBase):
), ),
) )
def testTimestampAdd(self, old_time, time_delta, expected_sec, expected_nano): def testTimestampAdd(self, old_time, time_delta, expected_sec, expected_nano):
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_timestamp = old_time msg.optional_timestamp = old_time
# Timestamp + timedelta # Timestamp + timedelta
new_msg1 = more_messages_pb2.WKTMessage() new_msg1 = well_known_types_test_pb2.WKTMessage()
new_msg1.optional_timestamp = msg.optional_timestamp + time_delta new_msg1.optional_timestamp = msg.optional_timestamp + time_delta
self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds) self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds)
self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos) self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos)
# timedelta + Timestamp # timedelta + Timestamp
new_msg2 = more_messages_pb2.WKTMessage() new_msg2 = well_known_types_test_pb2.WKTMessage()
new_msg2.optional_timestamp = time_delta + msg.optional_timestamp new_msg2.optional_timestamp = time_delta + msg.optional_timestamp
self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds) self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds)
self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos) self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos)
# Timestamp + Duration # Timestamp + Duration
msg.optional_duration.FromTimedelta(time_delta) msg.optional_duration.FromTimedelta(time_delta)
new_msg3 = more_messages_pb2.WKTMessage() new_msg3 = well_known_types_test_pb2.WKTMessage()
new_msg3.optional_timestamp = msg.optional_timestamp + msg.optional_duration new_msg3.optional_timestamp = msg.optional_timestamp + msg.optional_duration
self.assertEqual(expected_sec, new_msg3.optional_timestamp.seconds) self.assertEqual(expected_sec, new_msg3.optional_timestamp.seconds)
self.assertEqual(expected_nano, new_msg3.optional_timestamp.nanos) self.assertEqual(expected_nano, new_msg3.optional_timestamp.nanos)
@ -440,23 +442,23 @@ class TimeUtilTest(TimeUtilTestBase):
), ),
) )
def testTimestampSub(self, old_time, time_delta, expected_sec, expected_nano): def testTimestampSub(self, old_time, time_delta, expected_sec, expected_nano):
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_timestamp = old_time msg.optional_timestamp = old_time
# Timestamp - timedelta # Timestamp - timedelta
new_msg1 = more_messages_pb2.WKTMessage() new_msg1 = well_known_types_test_pb2.WKTMessage()
new_msg1.optional_timestamp = msg.optional_timestamp - time_delta new_msg1.optional_timestamp = msg.optional_timestamp - time_delta
self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds) self.assertEqual(expected_sec, new_msg1.optional_timestamp.seconds)
self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos) self.assertEqual(expected_nano, new_msg1.optional_timestamp.nanos)
# Timestamp - Duration # Timestamp - Duration
msg.optional_duration = time_delta msg.optional_duration = time_delta
new_msg2 = more_messages_pb2.WKTMessage() new_msg2 = well_known_types_test_pb2.WKTMessage()
new_msg2.optional_timestamp = msg.optional_timestamp - msg.optional_duration new_msg2.optional_timestamp = msg.optional_timestamp - msg.optional_duration
self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds) self.assertEqual(expected_sec, new_msg2.optional_timestamp.seconds)
self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos) self.assertEqual(expected_nano, new_msg2.optional_timestamp.nanos)
result_msg = more_messages_pb2.WKTMessage() result_msg = well_known_types_test_pb2.WKTMessage()
result_msg.optional_timestamp = old_time - time_delta result_msg.optional_timestamp = old_time - time_delta
# Timestamp - Timestamp # Timestamp - Timestamp
td = msg.optional_timestamp - result_msg.optional_timestamp td = msg.optional_timestamp - result_msg.optional_timestamp
@ -532,12 +534,12 @@ class TimeUtilTest(TimeUtilTestBase):
message.ToJsonString) message.ToJsonString)
self.assertRaisesRegex(ValueError, 'Timestamp is not valid', self.assertRaisesRegex(ValueError, 'Timestamp is not valid',
message.FromSeconds, -62135596801) message.FromSeconds, -62135596801)
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
msg.optional_timestamp = 1 msg.optional_timestamp = 1
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
msg2 = more_messages_pb2.WKTMessage(optional_timestamp=1) msg2 = well_known_types_test_pb2.WKTMessage(optional_timestamp=1)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
msg.optional_timestamp + '' msg.optional_timestamp + ''
@ -577,12 +579,12 @@ class TimeUtilTest(TimeUtilTestBase):
self.assertRaisesRegex(ValueError, self.assertRaisesRegex(ValueError,
r'Duration is not valid\: Sign mismatch.', r'Duration is not valid\: Sign mismatch.',
message.ToJsonString) message.ToJsonString)
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
msg.optional_duration = 1 msg.optional_duration = 1
with self.assertRaises(AttributeError): with self.assertRaises(AttributeError):
msg2 = more_messages_pb2.WKTMessage(optional_duration=1) msg2 = well_known_types_test_pb2.WKTMessage(optional_duration=1)
with self.assertRaises(TypeError): with self.assertRaises(TypeError):
msg.optional_duration + '' msg.optional_duration + ''
@ -594,7 +596,7 @@ class TimeUtilTest(TimeUtilTestBase):
('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000) ('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000)
) )
def testDurationAssignment(self, microseconds, expected_sec, expected_nano): def testDurationAssignment(self, microseconds, expected_sec, expected_nano):
message = more_messages_pb2.WKTMessage() message = well_known_types_test_pb2.WKTMessage()
expected_td = datetime.timedelta(microseconds=microseconds) expected_td = datetime.timedelta(microseconds=microseconds)
message.optional_duration = expected_td message.optional_duration = expected_td
self.assertEqual(expected_td, message.optional_duration.ToTimedelta()) self.assertEqual(expected_td, message.optional_duration.ToTimedelta())
@ -605,7 +607,7 @@ class TimeUtilTest(TimeUtilTestBase):
('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000) ('test1', -1999999, -1, -999999000), ('test2', 1999999, 1, 999999000)
) )
def testDurationCreation(self, microseconds, expected_sec, expected_nano): def testDurationCreation(self, microseconds, expected_sec, expected_nano):
message = more_messages_pb2.WKTMessage( message = well_known_types_test_pb2.WKTMessage(
optional_duration=datetime.timedelta(microseconds=microseconds) optional_duration=datetime.timedelta(microseconds=microseconds)
) )
expected_td = datetime.timedelta(microseconds=microseconds) expected_td = datetime.timedelta(microseconds=microseconds)
@ -630,24 +632,24 @@ class TimeUtilTest(TimeUtilTestBase):
), ),
) )
def testDurationAdd(self, old_time, time_delta, expected_sec, expected_nano): def testDurationAdd(self, old_time, time_delta, expected_sec, expected_nano):
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_duration = time_delta msg.optional_duration = time_delta
msg.optional_timestamp = old_time msg.optional_timestamp = old_time
# Duration + datetime # Duration + datetime
msg1 = more_messages_pb2.WKTMessage() msg1 = well_known_types_test_pb2.WKTMessage()
msg1.optional_timestamp = msg.optional_duration + old_time msg1.optional_timestamp = msg.optional_duration + old_time
self.assertEqual(expected_sec, msg1.optional_timestamp.seconds) self.assertEqual(expected_sec, msg1.optional_timestamp.seconds)
self.assertEqual(expected_nano, msg1.optional_timestamp.nanos) self.assertEqual(expected_nano, msg1.optional_timestamp.nanos)
# datetime + Duration # datetime + Duration
msg2 = more_messages_pb2.WKTMessage() msg2 = well_known_types_test_pb2.WKTMessage()
msg2.optional_timestamp = old_time + msg.optional_duration msg2.optional_timestamp = old_time + msg.optional_duration
self.assertEqual(expected_sec, msg2.optional_timestamp.seconds) self.assertEqual(expected_sec, msg2.optional_timestamp.seconds)
self.assertEqual(expected_nano, msg2.optional_timestamp.nanos) self.assertEqual(expected_nano, msg2.optional_timestamp.nanos)
# Duration + Timestamp # Duration + Timestamp
msg3 = more_messages_pb2.WKTMessage() msg3 = well_known_types_test_pb2.WKTMessage()
msg3.optional_timestamp = msg.optional_duration + msg.optional_timestamp msg3.optional_timestamp = msg.optional_duration + msg.optional_timestamp
self.assertEqual(expected_sec, msg3.optional_timestamp.seconds) self.assertEqual(expected_sec, msg3.optional_timestamp.seconds)
self.assertEqual(expected_nano, msg3.optional_timestamp.nanos) self.assertEqual(expected_nano, msg3.optional_timestamp.nanos)
@ -669,7 +671,7 @@ class TimeUtilTest(TimeUtilTestBase):
), ),
) )
def testDurationSub(self, old_time, time_delta, expected_sec, expected_nano): def testDurationSub(self, old_time, time_delta, expected_sec, expected_nano):
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_duration = time_delta msg.optional_duration = time_delta
# datetime - Duration # datetime - Duration
@ -843,7 +845,7 @@ class StructTest(unittest.TestCase):
'key2': 'abc', 'key2': 'abc',
'key3': {'subkey': 11.0, 'k': False}, 'key3': {'subkey': 11.0, 'k': False},
} }
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_struct = dictionary msg.optional_struct = dictionary
self.assertEqual(msg.optional_struct, dictionary) self.assertEqual(msg.optional_struct, dictionary)
@ -855,7 +857,7 @@ class StructTest(unittest.TestCase):
self.assertEqual(msg.optional_struct, dictionary2) self.assertEqual(msg.optional_struct, dictionary2)
# Tests assign empty # Tests assign empty
msg2 = more_messages_pb2.WKTMessage() msg2 = well_known_types_test_pb2.WKTMessage()
self.assertNotIn('optional_struct', msg2) self.assertNotIn('optional_struct', msg2)
msg2.optional_struct = {} msg2.optional_struct = {}
self.assertIn('optional_struct', msg2) self.assertIn('optional_struct', msg2)
@ -863,7 +865,7 @@ class StructTest(unittest.TestCase):
def testListValueAssignment(self): def testListValueAssignment(self):
list_value = [6, 'seven', True, False, None, {}] list_value = [6, 'seven', True, False, None, {}]
msg = more_messages_pb2.WKTMessage() msg = well_known_types_test_pb2.WKTMessage()
msg.optional_list_value = list_value msg.optional_list_value = list_value
self.assertEqual(msg.optional_list_value, list_value) self.assertEqual(msg.optional_list_value, list_value)
@ -874,7 +876,7 @@ class StructTest(unittest.TestCase):
'key3': {'subkey': 11.0, 'k': False}, 'key3': {'subkey': 11.0, 'k': False},
} }
list_value = [6, 'seven', True, False, None, dictionary] list_value = [6, 'seven', True, False, None, dictionary]
msg = more_messages_pb2.WKTMessage( msg = well_known_types_test_pb2.WKTMessage(
optional_struct=dictionary, optional_list_value=list_value optional_struct=dictionary, optional_list_value=list_value
) )
self.assertEqual(len(msg.optional_struct), len(dictionary)) self.assertEqual(len(msg.optional_struct), len(dictionary))
@ -882,7 +884,7 @@ class StructTest(unittest.TestCase):
self.assertEqual(len(msg.optional_list_value), len(list_value)) self.assertEqual(len(msg.optional_list_value), len(list_value))
self.assertEqual(msg.optional_list_value, list_value) self.assertEqual(msg.optional_list_value, list_value)
msg2 = more_messages_pb2.WKTMessage( msg2 = well_known_types_test_pb2.WKTMessage(
optional_struct={}, optional_list_value=[] optional_struct={}, optional_list_value=[]
) )
self.assertIn('optional_struct', msg2) self.assertIn('optional_struct', msg2)
@ -892,17 +894,17 @@ class StructTest(unittest.TestCase):
def testSpecialStructConstruct(self): def testSpecialStructConstruct(self):
dictionary = {'key1': 6.0} dictionary = {'key1': 6.0}
msg = more_messages_pb2.WKTMessage(optional_struct=dictionary) msg = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary)
self.assertEqual(msg.optional_struct, dictionary) self.assertEqual(msg.optional_struct, dictionary)
dictionary2 = {'fields': 7.0} dictionary2 = {'fields': 7.0}
msg2 = more_messages_pb2.WKTMessage(optional_struct=dictionary2) msg2 = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary2)
self.assertEqual(msg2.optional_struct, dictionary2) self.assertEqual(msg2.optional_struct, dictionary2)
# Construct Struct as normal message # Construct Struct as normal message
value_msg = struct_pb2.Value(number_value=5.0) value_msg = struct_pb2.Value(number_value=5.0)
dictionary3 = {'fields': {'key1': value_msg}} dictionary3 = {'fields': {'key1': value_msg}}
msg3 = more_messages_pb2.WKTMessage(optional_struct=dictionary3) msg3 = well_known_types_test_pb2.WKTMessage(optional_struct=dictionary3)
self.assertEqual(msg3.optional_struct, {'key1': 5.0}) self.assertEqual(msg3.optional_struct, {'key1': 5.0})
def testMergeFrom(self): def testMergeFrom(self):
@ -955,7 +957,7 @@ class AnyTest(unittest.TestCase):
def testAnyMessage(self): def testAnyMessage(self):
# Creates and sets message. # Creates and sets message.
msg = any_test_pb2.TestAny() msg = well_known_types_test_pb2.TestAny()
msg_descriptor = msg.DESCRIPTOR msg_descriptor = msg.DESCRIPTOR
all_types = unittest_pb2.TestAllTypes() all_types = unittest_pb2.TestAllTypes()
all_descriptor = all_types.DESCRIPTOR all_descriptor = all_types.DESCRIPTOR
@ -985,7 +987,7 @@ class AnyTest(unittest.TestCase):
msg_descriptor.full_name) msg_descriptor.full_name)
def testUnpackWithNoSlashInTypeUrl(self): def testUnpackWithNoSlashInTypeUrl(self):
msg = any_test_pb2.TestAny() msg = well_known_types_test_pb2.TestAny()
all_types = unittest_pb2.TestAllTypes() all_types = unittest_pb2.TestAllTypes()
all_descriptor = all_types.DESCRIPTOR all_descriptor = all_types.DESCRIPTOR
msg.value.Pack(all_types) msg.value.Pack(all_types)
@ -997,14 +999,14 @@ class AnyTest(unittest.TestCase):
def testMessageName(self): def testMessageName(self):
# Creates and sets message. # Creates and sets message.
submessage = any_test_pb2.TestAny() submessage = well_known_types_test_pb2.TestAny()
submessage.int_value = 12345 submessage.int_value = 12345
msg = any_pb2.Any() msg = any_pb2.Any()
msg.Pack(submessage) msg.Pack(submessage)
self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny') self.assertEqual(msg.TypeName(), 'google.protobuf.internal.TestAny')
def testPackWithCustomTypeUrl(self): def testPackWithCustomTypeUrl(self):
submessage = any_test_pb2.TestAny() submessage = well_known_types_test_pb2.TestAny()
submessage.int_value = 12345 submessage.int_value = 12345
msg = any_pb2.Any() msg = any_pb2.Any()
# Pack with a custom type URL prefix. # Pack with a custom type URL prefix.
@ -1020,12 +1022,12 @@ class AnyTest(unittest.TestCase):
self.assertEqual(msg.type_url, self.assertEqual(msg.type_url,
'/%s' % submessage.DESCRIPTOR.full_name) '/%s' % submessage.DESCRIPTOR.full_name)
# Test unpacking the type. # Test unpacking the type.
unpacked_message = any_test_pb2.TestAny() unpacked_message = well_known_types_test_pb2.TestAny()
self.assertTrue(msg.Unpack(unpacked_message)) self.assertTrue(msg.Unpack(unpacked_message))
self.assertEqual(submessage, unpacked_message) self.assertEqual(submessage, unpacked_message)
def testPackDeterministic(self): def testPackDeterministic(self):
submessage = any_test_pb2.TestAny() submessage = well_known_types_test_pb2.TestAny()
for i in range(10): for i in range(10):
submessage.map_value[str(i)] = i * 2 submessage.map_value[str(i)] = i * 2
msg = any_pb2.Any() msg = any_pb2.Any()

@ -34,7 +34,7 @@ class GeneratedProtocolMessageType(_message.MessageMeta):
mydescriptor = Descriptor(.....) mydescriptor = Descriptor(.....)
factory = symbol_database.Default() factory = symbol_database.Default()
factory.pool.AddDescriptor(mydescriptor) factory.pool.AddDescriptor(mydescriptor)
MyProtoClass = factory.GetPrototype(mydescriptor) MyProtoClass = message_factory.GetMessageClass(mydescriptor)
myproto_instance = MyProtoClass() myproto_instance = MyProtoClass()
myproto.foo_field = 23 myproto.foo_field = 23
... ...

@ -1,6 +1,12 @@
# Protobuf Rust runtime packages. # Protobuf Rust runtime packages.
load("@bazel_skylib//rules:common_settings.bzl", "string_flag") load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
# begin:github_only
load("@rules_pkg//pkg:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix")
load("@rules_pkg//pkg:zip.bzl", "pkg_zip")
# end:github_only
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test") load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
load("//bazel/toolchains:proto_lang_toolchain.bzl", "proto_lang_toolchain") load("//bazel/toolchains:proto_lang_toolchain.bzl", "proto_lang_toolchain")
@ -33,6 +39,7 @@ rust_library(
":use_upb_kernel": ["--cfg=upb_kernel"], ":use_upb_kernel": ["--cfg=upb_kernel"],
"//conditions:default": ["--cfg=cpp_kernel"], "//conditions:default": ["--cfg=cpp_kernel"],
}), }),
visibility = ["//visibility:public"],
deps = select({ deps = select({
":use_upb_kernel": [":protobuf_upb"], ":use_upb_kernel": [":protobuf_upb"],
"//conditions:default": [":protobuf_cpp"], "//conditions:default": [":protobuf_cpp"],
@ -47,17 +54,21 @@ rust_library(
# #
# shared.rs is the root of the crate and has public items re-exported in protobuf.rs for user use. # shared.rs is the root of the crate and has public items re-exported in protobuf.rs for user use.
PROTOBUF_SHARED = [ PROTOBUF_SHARED = [
# go/keep-sorted start
"codegen_traits.rs", "codegen_traits.rs",
"cord.rs",
"enum.rs", "enum.rs",
"internal.rs", "internal.rs",
"primitive.rs", "map.rs",
"optional.rs", "optional.rs",
"prelude.rs",
"primitive.rs",
"proto_macro.rs",
"proxied.rs", "proxied.rs",
"repeated.rs", "repeated.rs",
"shared.rs", "shared.rs",
"string.rs", "string.rs",
"map.rs", # go/keep-sorted end
"proto_macro.rs",
] ]
# The Rust Protobuf runtime using the upb kernel. # The Rust Protobuf runtime using the upb kernel.
@ -72,7 +83,10 @@ rust_library(
proc_macro_deps = [ proc_macro_deps = [
"@crate_index//:paste", "@crate_index//:paste",
], ],
rustc_flags = ["--cfg=upb_kernel"], rustc_flags = [
"--cfg=upb_kernel",
"--cfg=bzl",
],
visibility = [ visibility = [
"//rust:__subpackages__", "//rust:__subpackages__",
"//src/google/protobuf:__subpackages__", "//src/google/protobuf:__subpackages__",
@ -88,6 +102,7 @@ rust_test(
crate = ":protobuf_upb", crate = ":protobuf_upb",
rustc_flags = [ rustc_flags = [
"--cfg=upb_kernel", "--cfg=upb_kernel",
"--cfg=bzl",
], ],
deps = [ deps = [
"@crate_index//:googletest", "@crate_index//:googletest",
@ -131,6 +146,7 @@ rust_test(
crate = ":protobuf_cpp", crate = ":protobuf_cpp",
rustc_flags = [ rustc_flags = [
"--cfg=cpp_kernel", "--cfg=cpp_kernel",
"--cfg=bzl",
], ],
deps = [ deps = [
"@crate_index//:googletest", "@crate_index//:googletest",
@ -193,3 +209,57 @@ config_setting(
":rust_proto_library_kernel": "upb", ":rust_proto_library_kernel": "upb",
}, },
) )
# begin:github_only
pkg_files(
name = "rust_protobuf_src",
srcs = glob(
[
"*",
],
),
strip_prefix = strip_prefix.from_root("rust"),
visibility = ["//:__pkg__"],
)
pkg_files(
name = "crate_root_files",
srcs = glob(["cargo/**/*"]),
strip_prefix = strip_prefix.from_root("rust/cargo"),
visibility = ["//:__pkg__"],
)
pkg_filegroup(
name = "rust_protobuf_src_dir",
srcs = [
":rust_protobuf_src",
"//rust/upb:rust_protobuf_upb_src",
],
prefix = "src",
)
pkg_files(
name = "amalgamated_upb",
srcs = ["//upb:gen_amalgamation"],
strip_prefix = strip_prefix.from_root(""),
)
pkg_filegroup(
name = "rust_protobuf_libupb_src",
srcs = [
":amalgamated_upb",
"//upb/cmake:upb_cmake_dist",
],
prefix = "libupb",
)
pkg_zip(
name = "rust_crate",
srcs = [
":crate_root_files",
":rust_protobuf_libupb_src",
":rust_protobuf_src_dir",
"//:LICENSE",
],
)
# end:github_only

@ -0,0 +1,28 @@
# Protocol Buffers - Google's data interchange format
# Copyright 2024 Google LLC. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd
[package]
name = "protobuf"
version = "4.27.3-beta.0"
edition = "2021"
links = "libupb"
license = "BSD-3-Clause"
[lib]
path = "src/shared.rs"
[dependencies]
paste = "1.0.15"
[dev-dependencies]
googletest = {git = "https://github.com/google/googletest-rust.git" }
[build-dependencies]
cc = "1.1.6"
[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bzl)', 'cfg(cpp_kernel)', 'cfg(upb_kernel)'] }

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

Loading…
Cancel
Save