Skip to content

Commit

Permalink
Introduce lifetimes for individual feature values.
Browse files Browse the repository at this point in the history
This enables enforcement of lifetime specifications on individual enum values for features.  It will allow us to add new values to existing features, as well as deprecate/and remove existing values.  By default, each value will be scoped to the lifetime spec of its corresponding feature field.  However, individual lifetime boundaries can be overridden at the value-level for finer grained control.

In the near-term, this will allow us to deprecate/remove required field presence, and add a stricter utf8 validation feature.

PiperOrigin-RevId: 672710484
  • Loading branch information
mkruskal-google authored and copybara-github committed Sep 9, 2024
1 parent 49c0b4a commit 0b6e768
Show file tree
Hide file tree
Showing 7 changed files with 702 additions and 158 deletions.
2 changes: 1 addition & 1 deletion editions/defaults_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ TEST(DefaultsTest, CheckFuture) {
TEST(DefaultsTest, CheckFarFuture) {
auto defaults = ReadDefaults("test_defaults_far_future");
ASSERT_OK(defaults);
ASSERT_EQ(defaults->defaults().size(), 6);
ASSERT_EQ(defaults->defaults().size(), 7);
ASSERT_EQ(defaults->minimum_edition(), EDITION_99997_TEST_ONLY);
ASSERT_EQ(defaults->maximum_edition(), EDITION_99999_TEST_ONLY);

Expand Down
1 change: 1 addition & 0 deletions python/google/protobuf/internal/descriptor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1474,6 +1474,7 @@ class ReturnObject:
file = descriptor_pb2.FileDescriptorProto()
descriptor_pb2.DESCRIPTOR.CopyToProto(file)
ret.pool.Add(file)
file.Clear()
unittest_features_pb2.DESCRIPTOR.CopyToProto(file)
ret.pool.Add(file)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2097,7 +2097,7 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsWithExtension) {
FeatureSetDefaults defaults = ReadEditionDefaults("defaults");
EXPECT_EQ(defaults.minimum_edition(), EDITION_PROTO2);
EXPECT_EQ(defaults.maximum_edition(), EDITION_99999_TEST_ONLY);
ASSERT_EQ(defaults.defaults_size(), 6);
ASSERT_EQ(defaults.defaults_size(), 7);
EXPECT_EQ(defaults.defaults(0).edition(), EDITION_LEGACY);
EXPECT_EQ(defaults.defaults(2).edition(), EDITION_2023);
EXPECT_EQ(defaults.defaults(3).edition(), EDITION_2024);
Expand Down
88 changes: 54 additions & 34 deletions src/google/protobuf/descriptor_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10970,7 +10970,8 @@ TEST_F(FeaturesTest, RemovedFeature) {
}
)pb",
"foo.proto: foo.proto: NAME: Feature "
"pb.TestFeatures.removed_feature has been removed in edition 2024\n");
"pb.TestFeatures.removed_feature has been removed in edition 2024 and "
"can't be used in edition 2024\n");
}

TEST_F(FeaturesTest, RemovedFeatureDefault) {
Expand Down Expand Up @@ -11001,7 +11002,8 @@ TEST_F(FeaturesTest, FutureFeature) {
}
)pb",
"foo.proto: foo.proto: NAME: Feature "
"pb.TestFeatures.future_feature wasn't introduced until edition 2024\n");
"pb.TestFeatures.future_feature wasn't introduced until edition 2024 and "
"can't be used in edition 2023\n");
}

TEST_F(FeaturesTest, FutureFeatureDefault) {
Expand Down Expand Up @@ -12381,14 +12383,20 @@ TEST_F(DatabaseBackedPoolTest, UnittestProto) {
}

TEST_F(DatabaseBackedPoolTest, FeatureResolution) {
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
{
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
{
FileDescriptorProto proto;
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
AddToDatabase(&database_, R"pb(
name: "features.proto"
syntax: "editions"
Expand Down Expand Up @@ -12432,14 +12440,20 @@ TEST_F(DatabaseBackedPoolTest, FeatureResolution) {
}

TEST_F(DatabaseBackedPoolTest, FeatureLifetimeError) {
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
{
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
{
FileDescriptorProto proto;
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
AddToDatabase(&database_, R"pb(
name: "features.proto"
syntax: "editions"
Expand All @@ -12458,21 +12472,27 @@ TEST_F(DatabaseBackedPoolTest, FeatureLifetimeError) {
DescriptorPool pool(&database_, &error_collector);

EXPECT_TRUE(pool.FindMessageTypeByName("FooFeatures") == nullptr);
EXPECT_EQ(
error_collector.text_,
"features.proto: FooFeatures: NAME: Feature "
"pb.TestFeatures.future_feature wasn't introduced until edition 2024\n");
EXPECT_EQ(error_collector.text_,
"features.proto: FooFeatures: NAME: Feature "
"pb.TestFeatures.future_feature wasn't introduced until edition "
"2024 and can't be used in edition 2023\n");
}

TEST_F(DatabaseBackedPoolTest, FeatureLifetimeErrorUnknownDependencies) {
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
{
FileDescriptorProto proto;
FileDescriptorProto::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
{
FileDescriptorProto proto;
pb::TestFeatures::descriptor()->file()->CopyTo(&proto);
std::string text_proto;
google::protobuf::TextFormat::PrintToString(proto, &text_proto);
AddToDatabase(&database_, text_proto);
}
AddToDatabase(&database_, R"pb(
name: "option.proto"
syntax: "editions"
Expand Down Expand Up @@ -12522,10 +12542,10 @@ TEST_F(DatabaseBackedPoolTest, FeatureLifetimeErrorUnknownDependencies) {
// Verify that the extension does trigger a lifetime error.
error_collector.text_.clear();
ASSERT_EQ(pool.FindExtensionByName("foo_extension"), nullptr);
EXPECT_EQ(
error_collector.text_,
"option.proto: foo_extension: NAME: Feature "
"pb.TestFeatures.legacy_feature has been removed in edition 2023\n");
EXPECT_EQ(error_collector.text_,
"option.proto: foo_extension: NAME: Feature "
"pb.TestFeatures.legacy_feature has been removed in edition 2023 "
"and can't be used in edition 2023\n");
}

TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) {
Expand Down
Loading

0 comments on commit 0b6e768

Please sign in to comment.