@@ -67,6 +67,7 @@ class TestGenerator : public CodeGenerator {
67
67
}
68
68
69
69
// Expose the protected methods for testing.
70
+ using CodeGenerator::GetResolvedSourceFeatureExtension;
70
71
using CodeGenerator::GetResolvedSourceFeatures;
71
72
using CodeGenerator::GetUnresolvedSourceFeatures;
72
73
@@ -246,6 +247,143 @@ TEST_F(CodeGeneratorTest, GetResolvedSourceFeaturesInherited) {
246
247
EXPECT_EQ (ext.source_feature2 (), pb::EnumFeature::VALUE3);
247
248
}
248
249
250
+ TEST_F (CodeGeneratorTest, GetResolvedSourceFeatureExtension) {
251
+ TestGenerator generator;
252
+ generator.set_feature_extensions ({GetExtensionReflection (pb::test)});
253
+ ASSERT_OK (pool_.SetFeatureSetDefaults (*generator.BuildFeatureSetDefaults ()));
254
+
255
+ ASSERT_THAT (BuildFile (DescriptorProto::descriptor ()->file ()), NotNull ());
256
+ ASSERT_THAT (BuildFile (pb::TestMessage::descriptor ()->file ()), NotNull ());
257
+ auto file = BuildFile (R"schema(
258
+ edition = "2023";
259
+ package proto2_unittest;
260
+
261
+ import "google/protobuf/unittest_features.proto";
262
+
263
+ option features.(pb.test).file_feature = VALUE6;
264
+ option features.(pb.test).source_feature = VALUE5;
265
+ )schema" );
266
+ ASSERT_THAT (file, NotNull ());
267
+ const pb::TestFeatures& ext1 =
268
+ TestGenerator::GetResolvedSourceFeatureExtension (*file, pb::test);
269
+ const pb::TestFeatures& ext2 =
270
+ TestGenerator::GetResolvedSourceFeatures (*file).GetExtension (pb::test);
271
+
272
+ // Since the pool provides the feature set defaults, there should be no
273
+ // difference between the two results.
274
+ EXPECT_EQ (ext1.enum_feature (), pb::EnumFeature::VALUE1);
275
+ EXPECT_EQ (ext1.field_feature (), pb::EnumFeature::VALUE1);
276
+ EXPECT_EQ (ext1.file_feature (), pb::EnumFeature::VALUE6);
277
+ EXPECT_EQ (ext1.source_feature (), pb::EnumFeature::VALUE5);
278
+ EXPECT_EQ (ext2.enum_feature (), ext1.enum_feature ());
279
+ EXPECT_EQ (ext2.field_feature (), ext1.field_feature ());
280
+ EXPECT_EQ (ext2.file_feature (), ext1.file_feature ());
281
+ EXPECT_EQ (ext2.source_feature (), ext1.source_feature ());
282
+ }
283
+
284
+ TEST_F (CodeGeneratorTest, GetResolvedSourceFeatureExtensionEditedDefaults) {
285
+ FeatureSetDefaults defaults = ParseTextOrDie (R"pb(
286
+ minimum_edition: EDITION_PROTO2
287
+ maximum_edition: EDITION_2024
288
+ defaults {
289
+ edition: EDITION_LEGACY
290
+ overridable_features {}
291
+ fixed_features {
292
+ field_presence: EXPLICIT
293
+ enum_type: CLOSED
294
+ repeated_field_encoding: EXPANDED
295
+ utf8_validation: NONE
296
+ message_encoding: LENGTH_PREFIXED
297
+ json_format: LEGACY_BEST_EFFORT
298
+ enforce_naming_style: STYLE_LEGACY
299
+ default_symbol_visibility: EXPORT_ALL
300
+ }
301
+ }
302
+ defaults {
303
+ edition: EDITION_2023
304
+ overridable_features {
305
+ field_presence: EXPLICIT
306
+ enum_type: OPEN
307
+ repeated_field_encoding: PACKED
308
+ utf8_validation: VERIFY
309
+ message_encoding: LENGTH_PREFIXED
310
+ json_format: ALLOW
311
+ [pb.test] {
312
+ file_feature: VALUE3
313
+ field_feature: VALUE15
314
+ enum_feature: VALUE14
315
+ source_feature: VALUE1
316
+ }
317
+ }
318
+ fixed_features {
319
+ enforce_naming_style: STYLE_LEGACY
320
+ default_symbol_visibility: EXPORT_ALL
321
+ }
322
+ }
323
+ )pb" );
324
+ ASSERT_OK (pool_.SetFeatureSetDefaults (defaults));
325
+
326
+ ASSERT_THAT (BuildFile (DescriptorProto::descriptor ()->file ()), NotNull ());
327
+ ASSERT_THAT (BuildFile (pb::TestMessage::descriptor ()->file ()), NotNull ());
328
+ auto file = BuildFile (R"schema(
329
+ edition = "2023";
330
+ package proto2_unittest;
331
+
332
+ import "google/protobuf/unittest_features.proto";
333
+
334
+ option features.(pb.test).file_feature = VALUE6;
335
+ option features.(pb.test).source_feature = VALUE5;
336
+ )schema" );
337
+ ASSERT_THAT (file, NotNull ());
338
+ const pb::TestFeatures& ext =
339
+ TestGenerator::GetResolvedSourceFeatureExtension (*file, pb::test);
340
+
341
+ // Since the pool provides the modified feature set defaults, the result
342
+ // should be the one reflecting the pool's defaults.
343
+ EXPECT_EQ (ext.enum_feature (), pb::EnumFeature::VALUE14);
344
+ EXPECT_EQ (ext.field_feature (), pb::EnumFeature::VALUE15);
345
+ EXPECT_EQ (ext.file_feature (), pb::EnumFeature::VALUE6);
346
+ EXPECT_EQ (ext.source_feature (), pb::EnumFeature::VALUE5);
347
+ }
348
+
349
+ TEST_F (CodeGeneratorTest,
350
+ GetResolvedSourceFeatureExtensionDefaultsFromFeatureSetExtension) {
351
+ // Make sure feature set defaults are empty in the pool.
352
+ TestGenerator generator;
353
+ generator.set_feature_extensions ({});
354
+ ASSERT_OK (pool_.SetFeatureSetDefaults (*generator.BuildFeatureSetDefaults ()));
355
+
356
+ ASSERT_THAT (BuildFile (DescriptorProto::descriptor ()->file ()), NotNull ());
357
+ ASSERT_THAT (BuildFile (pb::TestMessage::descriptor ()->file ()), NotNull ());
358
+ auto file = BuildFile (R"schema(
359
+ edition = "2023";
360
+ package proto2_unittest;
361
+
362
+ import "google/protobuf/unittest_features.proto";
363
+
364
+ option features.(pb.test).file_feature = VALUE6;
365
+ option features.(pb.test).source_feature = VALUE5;
366
+ )schema" );
367
+ ASSERT_THAT (file, NotNull ());
368
+
369
+ const pb::TestFeatures& ext1 =
370
+ TestGenerator::GetResolvedSourceFeatureExtension (*file, pb::test);
371
+ const pb::TestFeatures& ext2 =
372
+ TestGenerator::GetResolvedSourceFeatures (*file).GetExtension (pb::test);
373
+
374
+ // No defaults were added to the pool, but they should be still present in the
375
+ // result. On the other hand, features that are explicitly set should be also
376
+ // present.
377
+ EXPECT_EQ (ext1.enum_feature (), pb::EnumFeature::VALUE1);
378
+ EXPECT_EQ (ext1.field_feature (), pb::EnumFeature::VALUE1);
379
+ EXPECT_EQ (ext1.file_feature (), pb::EnumFeature::VALUE6);
380
+ EXPECT_EQ (ext1.source_feature (), pb::EnumFeature::VALUE5);
381
+ EXPECT_EQ (ext2.enum_feature (), pb::EnumFeature::TEST_ENUM_FEATURE_UNKNOWN);
382
+ EXPECT_EQ (ext2.field_feature (), pb::EnumFeature::TEST_ENUM_FEATURE_UNKNOWN);
383
+ EXPECT_EQ (ext2.file_feature (), pb::EnumFeature::VALUE6);
384
+ EXPECT_EQ (ext2.source_feature (), pb::EnumFeature::VALUE5);
385
+ }
386
+
249
387
// TODO: Use the gtest versions once that's available in OSS.
250
388
MATCHER_P (HasError, msg_matcher, " " ) {
251
389
return arg.status ().code () == absl::StatusCode::kFailedPrecondition &&
0 commit comments