Enable conformance tests over editions protos

We transformed the proto2/proto3 protos to editions, and then run the same set of tests over both.  This will verify that migrating to editions preserves the same proto2/proto3 behavior.  These will not be enabled by default, and require a flag `--maximum_edition=2023`.

Future changes will:
- add more targeted editions-specific tests
- clean up our conformance test framework to allow for more targeted tests
- add wildcards to failure lists in limited cases to reduce noise
- add feature resolution conformance tests

PiperOrigin-RevId: 574570607
pull/14453/head
Mike Kruskal 2023-10-18 13:12:07 -07:00 committed by Copybara-Service
parent 898d8fa1fd
commit a2ba8bc78e
22 changed files with 257 additions and 92 deletions

View File

@ -33,12 +33,22 @@ add_custom_command(
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
DEPENDS ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
COMMAND ${protobuf_PROTOC_EXE} ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
--proto_path=${protobuf_SOURCE_DIR}/src
--cpp_out=${protoc_cpp_args}${protobuf_SOURCE_DIR}/src
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.cc
DEPENDS ${protobuf_PROTOC_EXE}
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto
COMMAND ${protobuf_PROTOC_EXE}
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.proto
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.proto
--proto_path=${protobuf_SOURCE_DIR}/src
--cpp_out=${protoc_cpp_args}${protobuf_SOURCE_DIR}/src
)
add_library(libconformance_common ${protobuf_SHARED_OR_STATIC}
@ -48,6 +58,10 @@ add_library(libconformance_common ${protobuf_SHARED_OR_STATIC}
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto3_editions.pb.cc
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.h
${protobuf_SOURCE_DIR}/src/google/protobuf/editions/golden/test_messages_proto2_editions.pb.cc
)
target_link_libraries(libconformance_common
${protobuf_LIB_PROTOBUF}
@ -100,6 +114,7 @@ add_test(NAME conformance_cpp_test
--failure_list ${protobuf_SOURCE_DIR}/conformance/failure_list_cpp.txt
--text_format_failure_list ${protobuf_SOURCE_DIR}/conformance/text_format_failure_list_cpp.txt
--output_dir ${protobuf_TEST_XML_OUTDIR}
--maximum_edition 2023
${CMAKE_CURRENT_BINARY_DIR}/conformance_cpp
DEPENDS conformance_test_runner conformance_cpp)

View File

@ -130,6 +130,7 @@ internal_ruby_proto_library(
cc_library(
name = "conformance_test",
testonly = 1,
srcs = [
"conformance_test.cc",
"conformance_test_runner.cc",
@ -151,12 +152,15 @@ cc_library(
cc_library(
name = "binary_json_conformance_suite",
testonly = 1,
srcs = ["binary_json_conformance_suite.cc"],
hdrs = ["binary_json_conformance_suite.h"],
deps = [
":conformance_test",
":test_messages_proto2_proto_cc",
":test_messages_proto3_proto_cc",
"//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto",
"//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto",
"@com_google_absl//absl/log:die_if_null",
"@com_google_absl//absl/status",
"@jsoncpp",
@ -165,12 +169,15 @@ cc_library(
cc_library(
name = "text_format_conformance_suite",
testonly = 1,
srcs = ["text_format_conformance_suite.cc"],
hdrs = ["text_format_conformance_suite.h"],
deps = [
":conformance_test",
":test_messages_proto2_proto_cc",
":test_messages_proto3_proto_cc",
"//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto",
"//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/log:die_if_null",
"@com_google_absl//absl/strings",
@ -179,6 +186,7 @@ cc_library(
cc_binary(
name = "conformance_test_runner",
testonly = 1,
srcs = ["conformance_test_main.cc"],
visibility = ["//visibility:public"],
deps = [
@ -199,6 +207,8 @@ cc_binary(
"//:protobuf",
"//:test_messages_proto2_cc_proto",
"//:test_messages_proto3_cc_proto",
"//src/google/protobuf/editions:test_messages_proto2_editions_cc_proto",
"//src/google/protobuf/editions:test_messages_proto3_editions_cc_proto",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
],

View File

@ -28,9 +28,10 @@ else
fi
# --- end runfiles.bash initialization ---
TESTEE=unset
FAILURE_LIST=unset
TEXT_FORMAT_FAILURE_LIST=unset
TESTEE=
FAILURE_LIST=
TEXT_FORMAT_FAILURE_LIST=
MAXIMUM_EDITION=
while [[ -n "$@" ]]; do
arg="$1"; shift
@ -39,6 +40,7 @@ while [[ -n "$@" ]]; do
"--testee") TESTEE="$val" ;;
"--failure_list") FAILURE_LIST="$val" ;;
"--text_format_failure_list") TEXT_FORMAT_FAILURE_LIST="$val" ;;
"--maximum_edition") MAXIMUM_EDITION="$val" ;;
*) echo "Flag $arg is not recognized." && exit 1 ;;
esac
done
@ -57,4 +59,8 @@ if [ -n "$text_format_failure_list" ]; then
args+=(--text_format_failure_list $text_format_failure_list)
fi
if [ -n "$MAXIMUM_EDITION" ]; then
args+=(--maximum_edition $MAXIMUM_EDITION)
fi
$conformance_test_runner "${args[@]}" $conformance_testee

View File

@ -24,9 +24,12 @@
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "json/json.h"
#include "conformance/conformance.pb.h"
#include "conformance_test.h"
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h"
#include "google/protobuf/endian.h"
#include "google/protobuf/json/json.h"
#include "google/protobuf/test_messages_proto2.pb.h"
@ -47,6 +50,10 @@ using google::protobuf::internal::little_endian::FromHost;
using google::protobuf::util::NewTypeResolverForDescriptorPool;
using protobuf_test_messages::proto2::TestAllTypesProto2;
using protobuf_test_messages::proto3::TestAllTypesProto3;
using TestAllTypesProto2Editions =
protobuf_test_messages::editions::proto2::TestAllTypesProto2;
using TestAllTypesProto3Editions =
protobuf_test_messages::editions::proto3::TestAllTypesProto3;
namespace {
@ -325,12 +332,17 @@ bool BinaryAndJsonConformanceSuite::ParseResponse(
void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
type_resolver_.reset(NewTypeResolverForDescriptorPool(
kTypeUrlPrefix, DescriptorPool::generated_pool()));
type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor());
BinaryAndJsonConformanceSuiteImpl<TestAllTypesProto3>(
this, /*run_proto3_tests=*/true);
BinaryAndJsonConformanceSuiteImpl<TestAllTypesProto2>(
this, /*run_proto3_tests=*/false);
if (maximum_edition_ >= Edition::EDITION_2023) {
BinaryAndJsonConformanceSuiteImpl<TestAllTypesProto3Editions>(
this, /*run_proto3_tests=*/true);
BinaryAndJsonConformanceSuiteImpl<TestAllTypesProto2Editions>(
this, /*run_proto3_tests=*/false);
}
}
template <typename MessageType>
@ -413,8 +425,7 @@ template <typename MessageType>
void BinaryAndJsonConformanceSuiteImpl<MessageType>::
RunValidJsonTestWithProtobufInput(
const std::string& test_name, ConformanceLevel level,
const TestAllTypesProto3& input,
const std::string& equivalent_text_format) {
const MessageType& input, const std::string& equivalent_text_format) {
ConformanceRequestSetting setting(
level, conformance::PROTOBUF, conformance::JSON, conformance::JSON_TEST,
input, test_name, input.SerializeAsString());
@ -427,7 +438,7 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
ConformanceLevel level,
const std::string& input_json,
const std::string& equivalent_text_format) {
TestAllTypesProto3 prototype;
MessageType prototype;
ConformanceRequestSetting setting(
level, conformance::JSON, conformance::PROTOBUF,
conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST, prototype, test_name,
@ -560,7 +571,7 @@ template <typename MessageType>
void BinaryAndJsonConformanceSuiteImpl<MessageType>::ExpectParseFailureForJson(
const std::string& test_name, ConformanceLevel level,
const std::string& input_json) {
TestAllTypesProto3 prototype;
MessageType prototype;
// We don't expect output, but if the program erroneously accepts the protobuf
// we let it send its response as this. We must not leave it unspecified.
ConformanceRequestSetting setting(level, conformance::JSON, conformance::JSON,
@ -568,8 +579,9 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::ExpectParseFailureForJson(
test_name, input_json);
const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response;
std::string effective_test_name = absl::StrCat(
setting.ConformanceLevelToString(level), ".Proto3.JsonInput.", test_name);
std::string effective_test_name =
absl::StrCat(setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".JsonInput.", test_name);
suite_.RunTest(effective_test_name, request, &response);
if (response.result_case() == ConformanceResponse::kParseError) {
@ -587,18 +599,19 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::
ExpectSerializeFailureForJson(const std::string& test_name,
ConformanceLevel level,
const std::string& text_format) {
TestAllTypesProto3 payload_message;
MessageType payload_message;
ABSL_CHECK(TextFormat::ParseFromString(text_format, &payload_message))
<< "Failed to parse: " << text_format;
TestAllTypesProto3 prototype;
MessageType prototype;
ConformanceRequestSetting setting(
level, conformance::PROTOBUF, conformance::JSON, conformance::JSON_TEST,
prototype, test_name, payload_message.SerializeAsString());
const ConformanceRequest& request = setting.GetRequest();
ConformanceResponse response;
std::string effective_test_name = absl::StrCat(
setting.ConformanceLevelToString(level), ".", test_name, ".JsonOutput");
std::string effective_test_name =
absl::StrCat(setting.ConformanceLevelToString(level), ".",
SyntaxIdentifier(), ".", test_name, ".JsonOutput");
suite_.RunTest(effective_test_name, request, &response);
if (response.result_case() == ConformanceResponse::kSerializeError) {
@ -1330,6 +1343,7 @@ BinaryAndJsonConformanceSuiteImpl<MessageType>::
BinaryAndJsonConformanceSuiteImpl(BinaryAndJsonConformanceSuite* suite,
bool run_proto3_tests)
: suite_(*ABSL_DIE_IF_NULL(suite)), run_proto3_tests_(run_proto3_tests) {
suite_.SetTypeUrl(GetTypeUrl(MessageType::GetDescriptor()));
RunAllTests();
}
@ -1666,15 +1680,18 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::RunJsonTests() {
"FieldName13": 0
})",
[](const Json::Value& value) { return value.isMember("FieldName13"); });
RunValidJsonTestWithValidator(
"FieldNameExtension", RECOMMENDED,
R"({
"[protobuf_test_messages.proto2.extension_int32]": 1
std::vector<const FieldDescriptor*> extensions;
MessageType::GetDescriptor()->file()->pool()->FindAllExtensions(
MessageType::GetDescriptor(), &extensions);
RunValidJsonTestWithValidator("FieldNameExtension", RECOMMENDED,
absl::Substitute(R"({
"[$0]": 1
})",
[](const Json::Value& value) {
return value.isMember(
"[protobuf_test_messages.proto2.extension_int32]");
});
extensions[0]->full_name()),
[&](const Json::Value& value) {
return value.isMember(absl::StrCat(
"[", extensions[0]->full_name(), "]"));
});
return;
}
RunValidJsonTest("HelloWorld", REQUIRED,
@ -2175,7 +2192,7 @@ void BinaryAndJsonConformanceSuiteImpl<
R"({"optionalFloat": "-Infinity"})", "optional_float: -inf");
// Non-canonical Nan will be correctly normalized.
{
TestAllTypesProto3 message;
MessageType message;
// IEEE floating-point standard 32-bit quiet NaN:
// 0111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
message.set_optional_float(WireFormatLite::DecodeFloat(0x7FA12345));
@ -2227,7 +2244,7 @@ void BinaryAndJsonConformanceSuiteImpl<
"optional_double: -inf");
// Non-canonical Nan will be correctly normalized.
{
TestAllTypesProto3 message;
MessageType message;
message.set_optional_double(
WireFormatLite::DecodeDouble(int64_t{0x7FFA123456789ABC}));
RunValidJsonTestWithProtobufInput("DoubleFieldNormalizeQuietNan", REQUIRED,
@ -3008,54 +3025,61 @@ void BinaryAndJsonConformanceSuiteImpl<MessageType>::RunJsonTestsForValue() {
template <typename MessageType>
void BinaryAndJsonConformanceSuiteImpl<MessageType>::RunJsonTestsForAny() {
std::string type_url = GetTypeUrl(MessageType::GetDescriptor());
RunValidJsonTest("Any", REQUIRED,
R"({
absl::Substitute(R"({
"optionalAny": {
"@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
"@type": "$0",
"optionalInt32": 12345
}
})",
R"(
GetTypeUrl(MessageType::GetDescriptor())),
absl::Substitute(R"(
optional_any: {
[type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
[$0] {
optional_int32: 12345
}
}
)");
}
}
)",
type_url));
RunValidJsonTest("AnyNested", REQUIRED,
R"({
absl::Substitute(R"({
"optionalAny": {
"@type": "type.googleapis.com/google.protobuf.Any",
"value": {
"@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3",
"@type": "$0",
"optionalInt32": 12345
}
}
})",
R"(
type_url),
absl::Substitute(R"(
optional_any: {
[type.googleapis.com/google.protobuf.Any] {
[type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
[type.googleapis.com/google.protobuf.Any] {
[$0] {
optional_int32: 12345
}
}
}
)");
}
}
}
)",
type_url));
// The special "@type" tag is not required to appear first.
RunValidJsonTest("AnyUnorderedTypeTag", REQUIRED,
R"({
absl::Substitute(R"({
"optionalAny": {
"optionalInt32": 12345,
"@type": "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
}
"@type": "$0"
}
})",
R"(
type_url),
absl::Substitute(R"(
optional_any: {
[type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
[$0] {
optional_int32: 12345
}
}
)");
}
}
)",
type_url));
// Well-known types in Any.
RunValidJsonTest("AnyWithInt32ValueWrapper", REQUIRED,
R"({
@ -3253,8 +3277,13 @@ std::string BinaryAndJsonConformanceSuiteImpl<MessageType>::SyntaxIdentifier()
const {
if constexpr (std::is_same<MessageType, TestAllTypesProto2>::value) {
return "Proto2";
} else {
} else if constexpr (std::is_same<MessageType, TestAllTypesProto3>::value) {
return "Proto3";
} else if constexpr (std::is_same<MessageType,
TestAllTypesProto2Editions>::value) {
return "Editions_Proto2";
} else {
return "Editions_Proto3";
}
}

View File

@ -14,6 +14,7 @@
#include <utility>
#include <vector>
#include "absl/strings/string_view.h"
#include "json/json.h"
#include "conformance_test.h"
#include "google/protobuf/descriptor.h"
@ -33,6 +34,9 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
bool ParseResponse(const conformance::ConformanceResponse& response,
const ConformanceRequestSetting& setting,
Message* test_message) override;
void SetTypeUrl(absl::string_view type_url) {
type_url_ = std::string(type_url);
}
template <typename MessageType>
friend class BinaryAndJsonConformanceSuiteImpl;
@ -44,8 +48,8 @@ class BinaryAndJsonConformanceSuite : public ConformanceTestSuite {
template <typename MessageType>
class BinaryAndJsonConformanceSuiteImpl {
public:
BinaryAndJsonConformanceSuiteImpl(BinaryAndJsonConformanceSuite* suite,
bool run_proto3_tests);
explicit BinaryAndJsonConformanceSuiteImpl(
BinaryAndJsonConformanceSuite* suite, bool run_proto3_tests);
private:
using ConformanceRequestSetting =
@ -79,8 +83,7 @@ class BinaryAndJsonConformanceSuiteImpl {
const Message& prototype);
void RunValidJsonTestWithProtobufInput(
const std::string& test_name, ConformanceLevel level,
const protobuf_test_messages::proto3::TestAllTypesProto3& input,
const std::string& equivalent_text_format);
const MessageType& input, const std::string& equivalent_text_format);
void RunValidJsonIgnoreUnknownTest(const std::string& test_name,
ConformanceLevel level,
const std::string& input_json,

View File

@ -21,6 +21,8 @@
#include "absl/status/statusor.h"
#include "conformance/conformance.pb.h"
#include "conformance/conformance.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h"
#include "google/protobuf/endian.h"
#include "google/protobuf/message.h"
#include "google/protobuf/test_messages_proto2.pb.h"
@ -45,6 +47,10 @@ using ::google::protobuf::util::NewTypeResolverForDescriptorPool;
using ::google::protobuf::util::TypeResolver;
using ::protobuf_test_messages::proto2::TestAllTypesProto2;
using ::protobuf_test_messages::proto3::TestAllTypesProto3;
using TestAllTypesProto2Editions =
::protobuf_test_messages::editions::proto2::TestAllTypesProto2;
using TestAllTypesProto3Editions =
::protobuf_test_messages::editions::proto3::TestAllTypesProto3;
absl::Status ReadFd(int fd, char* buf, size_t len) {
while (len > 0) {
@ -76,6 +82,8 @@ class Harness {
Harness() {
google::protobuf::LinkMessageReflection<TestAllTypesProto2>();
google::protobuf::LinkMessageReflection<TestAllTypesProto3>();
google::protobuf::LinkMessageReflection<TestAllTypesProto2Editions>();
google::protobuf::LinkMessageReflection<TestAllTypesProto3Editions>();
resolver_.reset(NewTypeResolverForDescriptorPool(
"type.googleapis.com", DescriptorPool::generated_pool()));

View File

@ -149,6 +149,16 @@ ConformanceTestSuite::ConformanceRequestSetting::GetSyntaxIdentifier() const {
return "Proto3";
case FileDescriptorLegacy::Syntax::SYNTAX_PROTO2:
return "Proto2";
case FileDescriptorLegacy::Syntax::SYNTAX_EDITIONS: {
std::string id = "Editions";
if (prototype_message_.GetDescriptor()->name() == "TestAllTypesProto2") {
absl::StrAppend(&id, "_Proto2");
} else if (prototype_message_.GetDescriptor()->name() ==
"TestAllTypesProto3") {
absl::StrAppend(&id, "_Proto3");
}
return id;
}
default:
return "Unknown";
}

View File

@ -132,6 +132,7 @@ class ConformanceTestSuite {
: verbose_(false),
performance_(false),
enforce_recommended_(false),
maximum_edition_(Edition::EDITION_PROTO3),
failure_list_flag_name_("--failure_list") {}
virtual ~ConformanceTestSuite() {}
@ -148,6 +149,9 @@ class ConformanceTestSuite {
// difference between REQUIRED and RECOMMENDED test cases.
void SetEnforceRecommended(bool value) { enforce_recommended_ = value; }
// Sets the maximum edition (inclusive) that should be tests for conformance.
void SetMaximumEdition(Edition edition) { maximum_edition_ = edition; }
// Gets the flag name to the failure list file.
// By default, this would return --failure_list
std::string GetFailureListFlagName() { return failure_list_flag_name_; }
@ -284,6 +288,7 @@ class ConformanceTestSuite {
bool verbose_;
bool performance_;
bool enforce_recommended_;
Edition maximum_edition_;
std::string output_;
std::string output_dir_;
std::string failure_list_flag_name_;

View File

@ -37,12 +37,15 @@
#include <unistd.h>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <future>
#include <vector>
#include "absl/log/absl_log.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "conformance/conformance.pb.h"
#include "conformance_test.h"
@ -119,6 +122,11 @@ void UsageError() {
fprintf(stderr,
" strictly conforming to protobuf\n");
fprintf(stderr, " spec.\n");
fprintf(stderr,
" --maximum edition Only run conformance tests up to \n");
fprintf(stderr,
" and including the specified\n");
fprintf(stderr, " edition.\n");
fprintf(stderr,
" --output_dir <dirname> Directory to write\n"
" output files.\n");
@ -200,6 +208,14 @@ int ForkPipeRunner::Run(int argc, char *argv[],
suite->SetVerbose(true);
} else if (strcmp(argv[arg], "--enforce_recommended") == 0) {
suite->SetEnforceRecommended(true);
} else if (strcmp(argv[arg], "--maximum_edition") == 0) {
if (++arg == argc) UsageError();
Edition edition = EDITION_UNKNOWN;
if (!Edition_Parse(absl::StrCat("EDITION_", argv[arg]), &edition)) {
fprintf(stderr, "Unknown edition: %s\n", argv[arg]);
UsageError();
}
suite->SetMaximumEdition(edition);
} else if (strcmp(argv[arg], "--output_dir") == 0) {
if (++arg == argc) UsageError();
suite->SetOutputDir(argv[arg]);

View File

@ -8,6 +8,7 @@ def conformance_test(
testee,
failure_list = None,
text_format_failure_list = None,
maximum_edition = None,
**kwargs):
"""Conformance test runner.
@ -27,6 +28,8 @@ def conformance_test(
if text_format_failure_list:
args = args + ["--text_format_failure_list %s" % _strip_bazel(text_format_failure_list)]
failure_lists = failure_lists + [text_format_failure_list]
if maximum_edition:
args = args + ["--maximum_edition %s" % maximum_edition]
native.sh_test(
name = name,

View File

@ -7,30 +7,57 @@
# TODO: insert links to corresponding bugs tracking the issue.
# Should we use GitHub issues or the Google-internal bug tracker?
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Proto3.JsonInput.FieldNameDuplicate
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate
Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing1
Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicateDifferentCasing2
Recommended.Proto3.JsonInput.FieldNameNotQuoted
Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted
Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Editions_Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
Recommended.Proto3.JsonInput.MapFieldValueIsNull
Recommended.Editions_Proto3.JsonInput.MapFieldValueIsNull
Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.Editions_Proto3.JsonInput.RepeatedFieldMessageElementIsNull
Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.Editions_Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
Recommended.Proto3.JsonInput.RepeatedFieldTrailingComma
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingComma
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithNewlines
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpace
Recommended.Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
Recommended.Editions_Proto3.JsonInput.RepeatedFieldTrailingCommaWithSpaceCommaSpace
Recommended.Proto3.JsonInput.StringFieldSingleQuoteBoth
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth
Recommended.Proto3.JsonInput.StringFieldSingleQuoteKey
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey
Recommended.Proto3.JsonInput.StringFieldSingleQuoteValue
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue
Recommended.Proto3.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.Editions_Proto3.JsonInput.StringFieldUppercaseEscapeLetter
Recommended.Proto3.JsonInput.TrailingCommaInAnObject
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObject
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithNewlines
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpace
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpace
Recommended.Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
Recommended.Editions_Proto3.JsonInput.TrailingCommaInAnObjectWithSpaceCommaSpace
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator

View File

@ -5,5 +5,5 @@ Required.Proto3.JsonInput.OneofFieldNullFirst.JsonOutput
Required.Proto3.JsonInput.OneofFieldNullFirst.ProtobufOutput
Required.Proto3.JsonInput.OneofFieldNullSecond.JsonOutput
Required.Proto3.JsonInput.OneofFieldNullSecond.ProtobufOutput
Recommended.ValueRejectInfNumberValue.JsonOutput
Recommended.ValueRejectNanNumberValue.JsonOutput
Recommended.Proto3.ValueRejectInfNumberValue.JsonOutput
Recommended.Proto3.ValueRejectNanNumberValue.JsonOutput

View File

@ -4,9 +4,9 @@
# 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.
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue
Recommended.Proto3.JsonInput.BoolFieldCamelCaseFalse

View File

@ -1,6 +1,6 @@
Recommended.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.Proto3.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Proto2.JsonInput.FieldNameExtension.Validator
Recommended.Proto3.JsonInput.BoolFieldAllCapitalFalse
Recommended.Proto3.JsonInput.BoolFieldAllCapitalTrue

View File

@ -15,6 +15,8 @@
#include "absl/log/die_if_null.h"
#include "absl/strings/str_cat.h"
#include "conformance_test.h"
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h"
#include "google/protobuf/test_messages_proto2.pb.h"
#include "google/protobuf/test_messages_proto3.pb.h"
#include "google/protobuf/text_format.h"
@ -25,6 +27,10 @@ using conformance::WireFormat;
using protobuf_test_messages::proto2::TestAllTypesProto2;
using protobuf_test_messages::proto2::UnknownToTestAllTypes;
using protobuf_test_messages::proto3::TestAllTypesProto3;
using TestAllTypesProto2Editions =
protobuf_test_messages::editions::proto2::TestAllTypesProto2;
using TestAllTypesProto3Editions =
protobuf_test_messages::editions::proto3::TestAllTypesProto3;
namespace google {
namespace protobuf {
@ -113,6 +119,10 @@ bool TextFormatConformanceTestSuite::ParseResponse(
void TextFormatConformanceTestSuite::RunSuiteImpl() {
TextFormatConformanceTestSuiteImpl<TestAllTypesProto2>(this);
TextFormatConformanceTestSuiteImpl<TestAllTypesProto3>(this);
if (maximum_edition_ >= Edition::EDITION_2023) {
TextFormatConformanceTestSuiteImpl<TestAllTypesProto2Editions>(this);
TextFormatConformanceTestSuiteImpl<TestAllTypesProto3Editions>(this);
}
}
template <typename MessageType>

View File

@ -1,20 +1,40 @@
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateFirstOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogatePairString
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyBytes
Recommended.Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralShortUnicodeEscapeSurrogateSecondOnlyString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairLongShortString
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongBytes
Recommended.Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
Recommended.Editions_Proto3.TextFormatInput.StringLiteralUnicodeEscapeSurrogatePairShortLongString
Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex
Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeBytes
Required.Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString
Required.Editions_Proto3.TextFormatInput.StringLiteralLongUnicodeEscapeTooLargeString

View File

@ -38,6 +38,7 @@ pkg_filegroup(
conformance_test(
name = "conformance_test",
failure_list = "//conformance:failure_list_cpp.txt",
maximum_edition = "2023",
testee = "//conformance:conformance_cpp",
text_format_failure_list = "//conformance:text_format_failure_list_cpp.txt",
)

View File

@ -85,22 +85,23 @@ cc_test(
)
proto_library(
name = "test_messages_proto2_proto",
name = "test_messages_proto2_editions_proto",
testonly = True,
srcs = ["golden/test_messages_proto2.proto"],
srcs = ["golden/test_messages_proto2_editions.proto"],
strip_import_prefix = "/src",
)
cc_proto_library(
name = "test_messages_proto2_cc_proto",
name = "test_messages_proto2_editions_cc_proto",
testonly = True,
deps = [":test_messages_proto2_proto"],
visibility = ["//conformance:__pkg__"],
deps = [":test_messages_proto2_editions_proto"],
)
proto_library(
name = "test_messages_proto3_proto",
name = "test_messages_proto3_editions_proto",
testonly = True,
srcs = ["golden/test_messages_proto3.proto"],
srcs = ["golden/test_messages_proto3_editions.proto"],
strip_import_prefix = "/src",
deps = [
"//:any_proto",
@ -113,9 +114,10 @@ proto_library(
)
cc_proto_library(
name = "test_messages_proto3_cc_proto",
name = "test_messages_proto3_editions_cc_proto",
testonly = True,
deps = [":test_messages_proto3_proto"],
visibility = ["//conformance:__pkg__"],
deps = [":test_messages_proto3_editions_proto"],
)
proto_library(
@ -136,8 +138,8 @@ cc_test(
srcs = ["generated_files_test.cc"],
deps = [
":test_editions_default_features_cc_proto",
":test_messages_proto2_cc_proto",
":test_messages_proto3_cc_proto",
":test_messages_proto2_editions_cc_proto",
":test_messages_proto3_editions_cc_proto",
"//:protobuf",
"//src/google/protobuf:test_textproto",
"@com_google_googletest//:gtest_main",
@ -148,7 +150,7 @@ cc_test(
name = "generated_reflection_test",
srcs = ["generated_reflection_test.cc"],
deps = [
":test_messages_proto2_cc_proto",
":test_messages_proto2_editions_cc_proto",
"@com_google_googletest//:gtest_main",
],
)

View File

@ -9,8 +9,8 @@
#include <gtest/gtest.h>
#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto2.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto3.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto3_editions.pb.h"
#include "google/protobuf/editions/proto/test_editions_default_features.pb.h"
#include "google/protobuf/test_textproto.h"
@ -22,9 +22,9 @@ namespace protobuf {
namespace {
using ::protobuf_editions_test::EditionsDefaultMessage;
using ::protobuf_test_messages::proto2::TestAllRequiredTypesProto2;
using ::protobuf_test_messages::proto2::TestAllTypesProto2;
using ::protobuf_test_messages::proto3::TestAllTypesProto3;
using ::protobuf_test_messages::editions::proto2::TestAllRequiredTypesProto2;
using ::protobuf_test_messages::editions::proto2::TestAllTypesProto2;
using ::protobuf_test_messages::editions::proto3::TestAllTypesProto3;
using ::testing::NotNull;
TEST(Generated, Parsing) {

View File

@ -6,13 +6,13 @@
// https://developers.google.com/open-source/licenses/bsd
#include <gtest/gtest.h>
#include "google/protobuf/editions/golden/test_messages_proto2.pb.h"
#include "google/protobuf/editions/golden/test_messages_proto2_editions.pb.h"
namespace google {
namespace protobuf {
namespace {
using ::protobuf_test_messages::proto2::TestAllTypesProto2;
using ::protobuf_test_messages::editions::proto2::TestAllTypesProto2;
// It's important that no calls that would initialize the generated pool occur
// in any tests in this file. This test guarantees that there's no mutex

View File

@ -13,13 +13,13 @@
edition = "2023";
package protobuf_test_messages.proto2;
package protobuf_test_messages.editions.proto2;
option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED;
option features.utf8_validation = NONE;
option features.json_format = LEGACY_BEST_EFFORT;
option java_package = "com.google.protobuf_test_messages.proto2";
option java_package = "com.google.protobuf_test_messages.editions.proto2";
option objc_class_prefix = "Proto2";
// This is the default, but we specify it here explicitly.

View File

@ -13,7 +13,7 @@
edition = "2023";
package protobuf_test_messages.proto3;
package protobuf_test_messages.editions.proto3;
import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
@ -23,7 +23,7 @@ import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
option features.field_presence = IMPLICIT;
option java_package = "com.google.protobuf_test_messages.proto3";
option java_package = "com.google.protobuf_test_messages.editions.proto3";
option objc_class_prefix = "Proto3";
// This is the default, but we specify it here explicitly.