Skip to content

Commit

Permalink
Breaking Change: Use Editions features in Java full runtimes.
Browse files Browse the repository at this point in the history
Note that this change breaks compatibility with old generated code from previous major versions per the Cross Version Runtime policy: https://protobuf.dev/support/cross-version-runtime-guarantee. This includes old gencode from <4.26.x, which does not resolve features.

PiperOrigin-RevId: 575230560
  • Loading branch information
zhangskz committed Dec 28, 2023
1 parent e9ea4a5 commit 3bb7ca7
Show file tree
Hide file tree
Showing 17 changed files with 672 additions and 203 deletions.
2 changes: 2 additions & 0 deletions conformance/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ java_binary(
"//:protobuf_java_util",
"//:test_messages_proto2_java_proto",
"//:test_messages_proto3_java_proto",
"//src/google/protobuf/editions:test_messages_proto2_editions_java_proto",
"//src/google/protobuf/editions:test_messages_proto3_editions_java_proto",
],
)

Expand Down
132 changes: 68 additions & 64 deletions conformance/ConformanceJava.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import com.google.protobuf.conformance.Conformance;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
import com.google.protobuf_test_messages.editions.proto2.TestMessagesProto2Editions;
import com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
Expand Down Expand Up @@ -205,42 +207,61 @@ private <T extends AbstractMessage> T parseBinary(
return messages.get(0);
}

private Class<? extends AbstractMessage> createTestMessage(String messageType) {
if (messageType.equals("protobuf_test_messages.proto3.TestAllTypesProto3")) {
return TestAllTypesProto3.class;
} else if (messageType.equals("protobuf_test_messages.proto2.TestAllTypesProto2")) {
return TestAllTypesProto2.class;
} else if (messageType.equals("protobuf_test_messages.editions.proto3.TestAllTypesProto3")) {
return TestMessagesProto3Editions.TestAllTypesProto3.class;
} else if (messageType.equals("protobuf_test_messages.editions.proto2.TestAllTypesProto2")) {
return TestMessagesProto2Editions.TestAllTypesProto2.class;
} else {
throw new IllegalArgumentException(
"Protobuf request has unexpected payload type: " + messageType);
}
}

private Class<?> createTestFile(String messageType) {
if (messageType.equals("protobuf_test_messages.proto3.TestAllTypesProto3")) {
return TestMessagesProto3.class;
} else if (messageType.equals("protobuf_test_messages.proto2.TestAllTypesProto2")) {
return TestMessagesProto2.class;
} else if (messageType.equals("protobuf_test_messages.editions.proto3.TestAllTypesProto3")) {
return TestMessagesProto3Editions.class;
} else if (messageType.equals("protobuf_test_messages.editions.proto2.TestAllTypesProto2")) {
return TestMessagesProto2Editions.class;
} else {
throw new IllegalArgumentException(
"Protobuf request has unexpected payload type: " + messageType);
}
}

@SuppressWarnings("unchecked")
private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
AbstractMessage testMessage;
String messageType = request.getMessageType();
boolean isProto3 = messageType.equals("protobuf_test_messages.proto3.TestAllTypesProto3");
boolean isProto2 = messageType.equals("protobuf_test_messages.proto2.TestAllTypesProto2");

switch (request.getPayloadCase()) {
case PROTOBUF_PAYLOAD:
{
if (isProto3) {
try {
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
TestMessagesProto3.registerAllExtensions(extensions);
testMessage =
parseBinary(
request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
} catch (InvalidProtocolBufferException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
}
} else if (isProto2) {
try {
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
TestMessagesProto2.registerAllExtensions(extensions);
testMessage =
parseBinary(
request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
} catch (InvalidProtocolBufferException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
}
} else {
throw new IllegalArgumentException(
"Protobuf request has unexpected payload type: " + messageType);
try {
ExtensionRegistry extensions = ExtensionRegistry.newInstance();
createTestFile(messageType)
.getMethod("registerAllExtensions", ExtensionRegistry.class)
.invoke(null, extensions);
testMessage =
parseBinary(
request.getProtobufPayload(),
(Parser<AbstractMessage>)
createTestMessage(messageType).getMethod("parser").invoke(null),
extensions);
} catch (InvalidProtocolBufferException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
}
Expand All @@ -252,54 +273,34 @@ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest re
== Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
parser = parser.ignoringUnknownFields();
}
if (isProto3) {
TestMessagesProto3.TestAllTypesProto3.Builder builder =
TestMessagesProto3.TestAllTypesProto3.newBuilder();
parser.merge(request.getJsonPayload(), builder);
testMessage = builder.build();
} else if (isProto2) {
TestMessagesProto2.TestAllTypesProto2.Builder builder =
TestMessagesProto2.TestAllTypesProto2.newBuilder();
parser.merge(request.getJsonPayload(), builder);
testMessage = builder.build();
} else {
throw new IllegalArgumentException(
"Protobuf request has unexpected payload type: " + messageType);
}
AbstractMessage.Builder<?> builder =
(AbstractMessage.Builder<?>)
createTestMessage(messageType).getMethod("newBuilder").invoke(null);
parser.merge(request.getJsonPayload(), builder);
testMessage = (AbstractMessage) builder.build();
} catch (InvalidProtocolBufferException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
}
case TEXT_PAYLOAD:
{
if (isProto3) {
try {
TestMessagesProto3.TestAllTypesProto3.Builder builder =
TestMessagesProto3.TestAllTypesProto3.newBuilder();
TextFormat.merge(request.getTextPayload(), builder);
testMessage = builder.build();
} catch (TextFormat.ParseException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
}
} else if (isProto2) {
try {
TestMessagesProto2.TestAllTypesProto2.Builder builder =
TestMessagesProto2.TestAllTypesProto2.newBuilder();
TextFormat.merge(request.getTextPayload(), builder);
testMessage = builder.build();
try {
AbstractMessage.Builder<?> builder =
(AbstractMessage.Builder<?>)
createTestMessage(messageType).getMethod("newBuilder").invoke(null);
TextFormat.merge(request.getTextPayload(), builder);
testMessage = (AbstractMessage) builder.build();
} catch (TextFormat.ParseException e) {
return Conformance.ConformanceResponse.newBuilder()
.setParseError(e.getMessage())
.build();
}
} else {
throw new IllegalArgumentException(
"Protobuf request has unexpected payload type: " + messageType);
} catch (Exception e) {
throw new RuntimeException(e);
}
break;
}
Expand Down Expand Up @@ -378,6 +379,9 @@ public void run() throws Exception {
typeRegistry =
TypeRegistry.newBuilder()
.add(TestMessagesProto3.TestAllTypesProto3.getDescriptor())
.add(
com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions
.TestAllTypesProto3.getDescriptor())
.build();
while (doTestIo()) {
this.testCount++;
Expand Down
39 changes: 39 additions & 0 deletions conformance/failure_list_java.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,42 @@ Required.Proto3.JsonInput.Int32FieldPlusSign
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.Proto3.JsonInput.StringFieldNotAString
Recommended.Editions_Proto3.FieldMaskNumbersDontRoundTrip.JsonOutput
Recommended.Editions_Proto3.FieldMaskPathsDontRoundTrip.JsonOutput
Recommended.Editions_Proto3.FieldMaskTooManyUnderscore.JsonOutput
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalFalse
Recommended.Editions_Proto3.JsonInput.BoolFieldAllCapitalTrue
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseFalse
Recommended.Editions_Proto3.JsonInput.BoolFieldCamelCaseTrue
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedFalse
Recommended.Editions_Proto3.JsonInput.BoolFieldDoubleQuotedTrue
Recommended.Editions_Proto3.JsonInput.BoolMapFieldKeyNotQuoted
Recommended.Editions_Proto3.JsonInput.DoubleFieldInfinityNotQuoted
Recommended.Editions_Proto3.JsonInput.DoubleFieldNanNotQuoted
Recommended.Editions_Proto3.JsonInput.DoubleFieldNegativeInfinityNotQuoted
Recommended.Editions_Proto3.JsonInput.FieldMaskInvalidCharacter
Recommended.Editions_Proto3.JsonInput.FieldNameDuplicate
Recommended.Editions_Proto3.JsonInput.FieldNameNotQuoted
Recommended.Editions_Proto3.JsonInput.FloatFieldInfinityNotQuoted
Recommended.Editions_Proto3.JsonInput.FloatFieldNanNotQuoted
Recommended.Editions_Proto3.JsonInput.FloatFieldNegativeInfinityNotQuoted
Recommended.Editions_Proto3.JsonInput.Int32MapFieldKeyNotQuoted
Recommended.Editions_Proto3.JsonInput.Int64MapFieldKeyNotQuoted
Recommended.Editions_Proto3.JsonInput.JsonWithComments
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteBoth
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteKey
Recommended.Editions_Proto3.JsonInput.StringFieldSingleQuoteValue
Recommended.Editions_Proto3.JsonInput.StringFieldSurrogateInWrongOrder
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedHighSurrogate
Recommended.Editions_Proto3.JsonInput.StringFieldUnpairedLowSurrogate
Recommended.Editions_Proto3.JsonInput.Uint32MapFieldKeyNotQuoted
Recommended.Editions_Proto3.JsonInput.Uint64MapFieldKeyNotQuoted
Recommended.Editions_Proto2.JsonInput.FieldNameExtension.Validator
Required.Editions_Proto3.JsonInput.EnumFieldNotQuoted
Required.Editions_Proto3.JsonInput.Int32FieldLeadingZero
Required.Editions_Proto3.JsonInput.Int32FieldNegativeWithLeadingZero
Required.Editions_Proto3.JsonInput.Int32FieldPlusSign
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotBool
Required.Editions_Proto3.JsonInput.RepeatedFieldWrongElementTypeExpectingStringsGotInt
Required.Editions_Proto3.JsonInput.StringFieldNotAString

8 changes: 8 additions & 0 deletions conformance/text_format_failure_list_java.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ Recommended.Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
Recommended.Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
Required.Proto3.TextFormatInput.AnyField.ProtobufOutput
Required.Proto3.TextFormatInput.AnyField.TextFormatOutput
Recommended.Editions_Proto3.ProtobufInput.GroupUnknownFields_Drop.TextFormatOutput
Recommended.Editions_Proto3.ProtobufInput.MessageUnknownFields_Drop.TextFormatOutput
Recommended.Editions_Proto3.ProtobufInput.RepeatedUnknownFields_Drop.TextFormatOutput
Recommended.Editions_Proto3.ProtobufInput.ScalarUnknownFields_Drop.TextFormatOutput
Required.Editions_Proto3.TextFormatInput.AnyField.ProtobufOutput
Required.Editions_Proto3.TextFormatInput.AnyField.TextFormatOutput

Required.Proto3.TextFormatInput.StringFieldBadUTF8Hex
Required.Proto3.TextFormatInput.StringFieldBadUTF8Octal
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Hex
Required.Editions_Proto3.TextFormatInput.StringFieldBadUTF8Octal
34 changes: 34 additions & 0 deletions java/core/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ load("//:protobuf_version.bzl", "PROTOBUF_JAVA_VERSION")
load("//build_defs:java_opts.bzl", "protobuf_java_export", "protobuf_java_library", "protobuf_versioned_java_library")
load("//conformance:defs.bzl", "conformance_test")
load("//java/internal:testing.bzl", "junit_tests")
load("//src/google/protobuf/editions:defaults.bzl", "compile_edition_defaults", "embed_edition_defaults")

LITE_SRCS = [
# Keep in sync with `//java/lite:pom.xml`.
Expand Down Expand Up @@ -168,13 +169,21 @@ protobuf_java_library(
proto_library(
name = "java_features_proto",
srcs = ["src/main/java/com/google/protobuf/java_features.proto"],
strip_import_prefix = "/java/core/src/main/java/com",
visibility = ["//pkg:__pkg__"],
deps = ["//:descriptor_proto"],
)

filegroup(
name = "java_features_proto_srcs",
srcs = ["src/main/java/com/google/protobuf/java_features.proto"],
visibility = ["//pkg:__pkg__"],
)

internal_gen_well_known_protos_java(
name = "gen_well_known_protos_java",
deps = [
":java_features_proto",
"//:any_proto",
"//:api_proto",
"//:compiler_plugin_proto",
Expand All @@ -198,6 +207,7 @@ java_library(
],
exclude = LITE_SRCS,
) + [
"src/main/java/com/google/protobuf/JavaEditionDefaults.java",
":gen_well_known_protos_java",
],
visibility = ["//visibility:public"],
Expand All @@ -217,6 +227,7 @@ protobuf_versioned_java_library(
],
exclude = LITE_SRCS,
) + [
"src/main/java/com/google/protobuf/JavaEditionDefaults.java",
":gen_well_known_protos_java",
],
automatic_module_name = "com.google.protobuf",
Expand All @@ -240,6 +251,7 @@ protobuf_java_export(
maven_coordinates = "com.google.protobuf:protobuf-java:%s" % PROTOBUF_JAVA_VERSION,
pom_template = "pom_template.xml",
resources = [
":java_features_proto_srcs",
"//:well_known_type_protos",
"//src/google/protobuf:descriptor_proto_srcs",
],
Expand All @@ -266,6 +278,7 @@ proto_lang_toolchain(
name = "toolchain",
# keep this in sync w/ WELL_KNOWN_PROTO_MAP in //:BUILD
blacklisted_protos = [
":java_features_proto",
"//:any_proto",
"//:api_proto",
"//:compiler_plugin_proto",
Expand Down Expand Up @@ -355,6 +368,7 @@ build_test(
conformance_test(
name = "conformance_test",
failure_list = "//conformance:failure_list_java.txt",
maximum_edition = "2023",
testee = "//conformance:conformance_java",
text_format_failure_list = "//conformance:text_format_failure_list_java.txt",
)
Expand Down Expand Up @@ -527,10 +541,29 @@ junit_tests(
],
)

compile_edition_defaults(
name = "java_edition_defaults",
srcs = [
":java_features_proto",
"//:descriptor_proto",
],
maximum_edition = "2023",
minimum_edition = "PROTO2",
)

embed_edition_defaults(
name = "embedded_java_edition_defaults_generate",
defaults = "java_edition_defaults",
output = "src/main/java/com/google/protobuf/JavaEditionDefaults.java",
placeholder = "DEFAULTS_VALUE",
template = "src/main/java/com/google/protobuf/JavaEditionDefaults.java.template",
)

pkg_files(
name = "dist_files",
srcs = glob([
"src/main/java/com/google/protobuf/*.java",
"src/main/java/com/google/protobuf/*.proto",
"src/test/java/**/*.java",
"src/test/proto/**/*.proto",
]) + [
Expand All @@ -539,6 +572,7 @@ pkg_files(
"generate-test-sources-build.xml",
"pom.xml",
"pom_template.xml",
"src/main/java/com/google/protobuf/JavaEditionDefaults.java",
],
strip_prefix = strip_prefix.from_root(""),
visibility = ["//java:__pkg__"],
Expand Down
2 changes: 2 additions & 0 deletions java/core/generate-sources-build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<exec executable="${protoc}">
<arg value="--java_out=${generated.sources.dir}"/>
<arg value="--proto_path=${protobuf.source.dir}"/>
<arg value="--proto_path=${protobuf.java_source.dir}"/>
<arg value="${protobuf.java_source.dir}/main/java/com/google/protobuf/java_features.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/any.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/api.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/descriptor.proto"/>
Expand Down
6 changes: 6 additions & 0 deletions java/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@
<include>google/protobuf/compiler/plugin.proto</include>
</includes>
</resource>
<resource>
<directory>${protobuf.java_source.dir}</directory>
<includes>
<include>main/java/com/google/protobuf/java_features.proto</include>
</includes>
</resource>
</resources>
<testResources>
<testResource>
Expand Down
Loading

0 comments on commit 3bb7ca7

Please sign in to comment.