#region Copyright notice and license // 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 #endregion using Google.Protobuf.Reflection; using NUnit.Framework; using Pb; using static Google.Protobuf.Reflection.FieldDescriptorProto.Types; using Type = Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type; namespace Google.Protobuf.Test.Reflection; public class FeatureInheritanceTest { // Note: there's no test for file defaults, as we don't have the same access to modify the // global defaults in C# that exists in Java. [Test] public void FileOverrides() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.Features)); } [Test] public void FileMessageInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Features)); } [Test] public void FileMessageOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); SetTestFeature(fileProto.MessageType[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Features)); } [Test] public void FileEnumInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); } [Test] public void FileEnumOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); SetTestFeature(fileProto.EnumType[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); } [Test] public void FileExtensionInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); } [Test] public void FileExtensionOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); SetTestFeature(fileProto.Extension[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.Extensions.UnorderedExtensions[0].Features)); } [Test] public void FileServiceInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.Services[0].Features)); } [Test] public void FileServiceOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto, 3); SetTestFeature(fileProto.Service[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.Services[0].Features)); } [Test] public void MessageFieldInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Fields.InFieldNumberOrder()[0].Features)); } [Test] public void MessageFieldOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].Field[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Fields.InFieldNumberOrder()[0].Features)); } [Test] public void MessageEnumInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].EnumTypes[0].Features)); } [Test] public void MessageEnumOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].EnumType[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].EnumTypes[0].Features)); } [Test] public void MessageMessageInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].NestedTypes[0].Features)); } [Test] public void MessageMessageOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].NestedType[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].NestedTypes[0].Features)); } [Test] public void MessageExtensionInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Extensions.UnorderedExtensions[0].Features)); } [Test] public void MessageExtensionOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].Extension[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Extensions.UnorderedExtensions[0].Features)); } [Test] public void MessageOneofInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Features)); } [Test] public void MessageOneofOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].OneofDecl[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Fields[0].Features)); } [Test] public void OneofFieldInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Fields[0].Features)); } [Test] public void OneofFieldOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.MessageType[0].OneofDecl[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Features)); } [Test] public void EnumValueInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.EnumType[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Values[0].Features)); } [Test] public void EnumValueOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.MessageType[0], 3); SetTestFeature(fileProto.EnumType[0].Value[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.EnumTypes[0].Values[0].Features)); } [Test] public void ServiceMethodInherit() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.Service[0], 3); var fileDescriptor = Build(fileProto); Assert.AreEqual(3, GetTestFeature(fileDescriptor.Services[0].Methods[0].Features)); } [Test] public void ServiceMethodOverride() { var fileProto = CreateFileProto(); SetTestFeature(fileProto.Service[0], 3); SetTestFeature(fileProto.Service[0].Method[0], 5); var fileDescriptor = Build(fileProto); Assert.AreEqual(5, GetTestFeature(fileDescriptor.Services[0].Methods[0].Features)); } private static int GetTestFeature(FeatureSetDescriptor features) => (int)(features.Proto.GetExtension(UnittestFeaturesExtensions.Test) ?? new TestFeatures()) .MultipleFeature; private static void SetTestFeature(FileDescriptorProto proto, int value) { proto.Options ??= new FileOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(DescriptorProto proto, int value) { proto.Options ??= new MessageOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(EnumDescriptorProto proto, int value) { proto.Options ??= new EnumOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(EnumValueDescriptorProto proto, int value) { proto.Options ??= new EnumValueOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(FieldDescriptorProto proto, int value) { proto.Options ??= new FieldOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(ServiceDescriptorProto proto, int value) { proto.Options ??= new ServiceOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(OneofDescriptorProto proto, int value) { proto.Options ??= new OneofOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(MethodDescriptorProto proto, int value) { proto.Options ??= new MethodOptions(); proto.Options.Features ??= new FeatureSet(); SetTestFeature(proto.Options.Features, value); } private static void SetTestFeature(FeatureSet features, int value) => features.SetExtension(UnittestFeaturesExtensions.Test, new TestFeatures { MultipleFeature = (Pb.EnumFeature)value }); private static FileDescriptor Build(FileDescriptorProto fileProto) => FileDescriptor.BuildFromByteStrings(new[] { fileProto.ToByteString() }, new ExtensionRegistry { UnittestFeaturesExtensions.Test })[0]; private static FileDescriptorProto CreateFileProto() => new FileDescriptorProto { Name = "some/filename/some.proto", Package = "proto2_unittest", Edition = Edition._2023, Syntax = "editions", Extension = { new FieldDescriptorProto { Name = "top_extension", Number = 10, Type = Type.Int32, Label = Label.Optional, Extendee = ".proto2_unittest.TopMessage" } }, EnumType = { new EnumDescriptorProto { Name = "TopEnum", Value = { new EnumValueDescriptorProto { Name = "TOP_VALUE", Number = 0 } } } }, MessageType = { new DescriptorProto { Name = "TopMessage", Field = { new FieldDescriptorProto { Name = "field", Number = 1, Type = Type.Int32, Label = Label.Optional }, new FieldDescriptorProto { Name = "oneof_field", Number = 2, Type = Type.Int32, Label = Label.Optional, OneofIndex = 0 } }, Extension = { new FieldDescriptorProto { Name = "nested_extension", Number = 11, Type = Type.Int32, Label = Label.Optional, Extendee = ".proto2_unittest.TopMessage" } }, NestedType = { new DescriptorProto { Name = "NestedMessage" }, }, EnumType = { new EnumDescriptorProto { Name = "NestedEnum", Value = { new EnumValueDescriptorProto { Name = "NESTED_VALUE", Number = 0 } } } }, OneofDecl = { new OneofDescriptorProto { Name = "Oneof" } } } }, Service = { new ServiceDescriptorProto { Name = "TestService", Method = { new MethodDescriptorProto { Name = "CallMethod", InputType = ".proto2_unittest.TopMessage", OutputType = ".proto2_unittest.TopMessage" } } } } }; }