1 #region Copyright notice and license 2 // Protocol Buffers - Google's data interchange format 3 // Copyright 2008 Google Inc. All rights reserved. 4 // 5 // Use of this source code is governed by a BSD-style 6 // license that can be found in the LICENSE file or at 7 // https://developers.google.com/open-source/licenses/bsd 8 #endregion 9 10 using Google.Protobuf.Reflection; 11 using NUnit.Framework; 12 using Pb; 13 using static Google.Protobuf.Reflection.FieldDescriptorProto.Types; 14 using Type = Google.Protobuf.Reflection.FieldDescriptorProto.Types.Type; 15 16 namespace Google.Protobuf.Test.Reflection; 17 18 public class FeatureInheritanceTest 19 { 20 // Note: there's no test for file defaults, as we don't have the same access to modify the 21 // global defaults in C# that exists in Java. 22 23 [Test] FileOverrides()24 public void FileOverrides() 25 { 26 var fileProto = CreateFileProto(); 27 SetTestFeature(fileProto, 3); 28 var fileDescriptor = Build(fileProto); 29 Assert.AreEqual(3, GetTestFeature(fileDescriptor.Features)); 30 } 31 32 [Test] FileMessageInherit()33 public void FileMessageInherit() 34 { 35 var fileProto = CreateFileProto(); 36 SetTestFeature(fileProto, 3); 37 var fileDescriptor = Build(fileProto); 38 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Features)); 39 } 40 41 [Test] FileMessageOverride()42 public void FileMessageOverride() 43 { 44 var fileProto = CreateFileProto(); 45 SetTestFeature(fileProto, 3); 46 SetTestFeature(fileProto.MessageType[0], 5); 47 var fileDescriptor = Build(fileProto); 48 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Features)); 49 } 50 51 [Test] FileEnumInherit()52 public void FileEnumInherit() 53 { 54 var fileProto = CreateFileProto(); 55 SetTestFeature(fileProto, 3); 56 var fileDescriptor = Build(fileProto); 57 Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); 58 } 59 60 [Test] FileEnumOverride()61 public void FileEnumOverride() 62 { 63 var fileProto = CreateFileProto(); 64 SetTestFeature(fileProto, 3); 65 SetTestFeature(fileProto.EnumType[0], 5); 66 var fileDescriptor = Build(fileProto); 67 Assert.AreEqual(5, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); 68 } 69 70 [Test] FileExtensionInherit()71 public void FileExtensionInherit() 72 { 73 var fileProto = CreateFileProto(); 74 SetTestFeature(fileProto, 3); 75 var fileDescriptor = Build(fileProto); 76 Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Features)); 77 } 78 79 [Test] FileExtensionOverride()80 public void FileExtensionOverride() 81 { 82 var fileProto = CreateFileProto(); 83 SetTestFeature(fileProto, 3); 84 SetTestFeature(fileProto.Extension[0], 5); 85 var fileDescriptor = Build(fileProto); 86 Assert.AreEqual(5, GetTestFeature(fileDescriptor.Extensions.UnorderedExtensions[0].Features)); 87 } 88 89 [Test] FileServiceInherit()90 public void FileServiceInherit() 91 { 92 var fileProto = CreateFileProto(); 93 SetTestFeature(fileProto, 3); 94 var fileDescriptor = Build(fileProto); 95 Assert.AreEqual(3, GetTestFeature(fileDescriptor.Services[0].Features)); 96 } 97 98 [Test] FileServiceOverride()99 public void FileServiceOverride() 100 { 101 var fileProto = CreateFileProto(); 102 SetTestFeature(fileProto, 3); 103 SetTestFeature(fileProto.Service[0], 5); 104 var fileDescriptor = Build(fileProto); 105 Assert.AreEqual(5, GetTestFeature(fileDescriptor.Services[0].Features)); 106 } 107 108 [Test] MessageFieldInherit()109 public void MessageFieldInherit() 110 { 111 var fileProto = CreateFileProto(); 112 SetTestFeature(fileProto.MessageType[0], 3); 113 var fileDescriptor = Build(fileProto); 114 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Fields.InFieldNumberOrder()[0].Features)); 115 } 116 117 [Test] MessageFieldOverride()118 public void MessageFieldOverride() 119 { 120 var fileProto = CreateFileProto(); 121 SetTestFeature(fileProto.MessageType[0], 3); 122 SetTestFeature(fileProto.MessageType[0].Field[0], 5); 123 var fileDescriptor = Build(fileProto); 124 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Fields.InFieldNumberOrder()[0].Features)); 125 } 126 127 [Test] MessageEnumInherit()128 public void MessageEnumInherit() 129 { 130 var fileProto = CreateFileProto(); 131 SetTestFeature(fileProto.MessageType[0], 3); 132 var fileDescriptor = Build(fileProto); 133 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].EnumTypes[0].Features)); 134 } 135 136 [Test] MessageEnumOverride()137 public void MessageEnumOverride() 138 { 139 var fileProto = CreateFileProto(); 140 SetTestFeature(fileProto.MessageType[0], 3); 141 SetTestFeature(fileProto.MessageType[0].EnumType[0], 5); 142 var fileDescriptor = Build(fileProto); 143 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].EnumTypes[0].Features)); 144 } 145 146 [Test] MessageMessageInherit()147 public void MessageMessageInherit() 148 { 149 var fileProto = CreateFileProto(); 150 SetTestFeature(fileProto.MessageType[0], 3); 151 var fileDescriptor = Build(fileProto); 152 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].NestedTypes[0].Features)); 153 } 154 155 [Test] MessageMessageOverride()156 public void MessageMessageOverride() 157 { 158 var fileProto = CreateFileProto(); 159 SetTestFeature(fileProto.MessageType[0], 3); 160 SetTestFeature(fileProto.MessageType[0].NestedType[0], 5); 161 var fileDescriptor = Build(fileProto); 162 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].NestedTypes[0].Features)); 163 } 164 165 [Test] MessageExtensionInherit()166 public void MessageExtensionInherit() 167 { 168 var fileProto = CreateFileProto(); 169 SetTestFeature(fileProto.MessageType[0], 3); 170 var fileDescriptor = Build(fileProto); 171 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Extensions.UnorderedExtensions[0].Features)); 172 } 173 174 [Test] MessageExtensionOverride()175 public void MessageExtensionOverride() 176 { 177 var fileProto = CreateFileProto(); 178 SetTestFeature(fileProto.MessageType[0], 3); 179 SetTestFeature(fileProto.MessageType[0].Extension[0], 5); 180 var fileDescriptor = Build(fileProto); 181 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Extensions.UnorderedExtensions[0].Features)); 182 } 183 184 [Test] MessageOneofInherit()185 public void MessageOneofInherit() 186 { 187 var fileProto = CreateFileProto(); 188 SetTestFeature(fileProto.MessageType[0], 3); 189 var fileDescriptor = Build(fileProto); 190 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Features)); 191 } 192 193 [Test] MessageOneofOverride()194 public void MessageOneofOverride() 195 { 196 var fileProto = CreateFileProto(); 197 SetTestFeature(fileProto.MessageType[0], 3); 198 SetTestFeature(fileProto.MessageType[0].OneofDecl[0], 5); 199 var fileDescriptor = Build(fileProto); 200 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Fields[0].Features)); 201 } 202 203 [Test] OneofFieldInherit()204 public void OneofFieldInherit() 205 { 206 var fileProto = CreateFileProto(); 207 SetTestFeature(fileProto.MessageType[0], 3); 208 var fileDescriptor = Build(fileProto); 209 Assert.AreEqual(3, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Fields[0].Features)); 210 } 211 212 [Test] OneofFieldOverride()213 public void OneofFieldOverride() 214 { 215 var fileProto = CreateFileProto(); 216 SetTestFeature(fileProto.MessageType[0], 3); 217 SetTestFeature(fileProto.MessageType[0].OneofDecl[0], 5); 218 var fileDescriptor = Build(fileProto); 219 Assert.AreEqual(5, GetTestFeature(fileDescriptor.MessageTypes[0].Oneofs[0].Features)); 220 } 221 222 [Test] EnumValueInherit()223 public void EnumValueInherit() 224 { 225 var fileProto = CreateFileProto(); 226 SetTestFeature(fileProto.EnumType[0], 3); 227 var fileDescriptor = Build(fileProto); 228 Assert.AreEqual(3, GetTestFeature(fileDescriptor.EnumTypes[0].Values[0].Features)); 229 } 230 231 [Test] EnumValueOverride()232 public void EnumValueOverride() 233 { 234 var fileProto = CreateFileProto(); 235 SetTestFeature(fileProto.MessageType[0], 3); 236 SetTestFeature(fileProto.EnumType[0].Value[0], 5); 237 var fileDescriptor = Build(fileProto); 238 Assert.AreEqual(5, GetTestFeature(fileDescriptor.EnumTypes[0].Values[0].Features)); 239 } 240 241 [Test] ServiceMethodInherit()242 public void ServiceMethodInherit() 243 { 244 var fileProto = CreateFileProto(); 245 SetTestFeature(fileProto.Service[0], 3); 246 var fileDescriptor = Build(fileProto); 247 Assert.AreEqual(3, GetTestFeature(fileDescriptor.Services[0].Methods[0].Features)); 248 } 249 250 [Test] ServiceMethodOverride()251 public void ServiceMethodOverride() 252 { 253 var fileProto = CreateFileProto(); 254 SetTestFeature(fileProto.Service[0], 3); 255 SetTestFeature(fileProto.Service[0].Method[0], 5); 256 var fileDescriptor = Build(fileProto); 257 Assert.AreEqual(5, GetTestFeature(fileDescriptor.Services[0].Methods[0].Features)); 258 } 259 260 private static int GetTestFeature(FeatureSetDescriptor features) => 261 (int)(features.Proto.GetExtension(UnittestFeaturesExtensions.Test) ?? new TestFeatures()) 262 .MultipleFeature; 263 SetTestFeature(FileDescriptorProto proto, int value)264 private static void SetTestFeature(FileDescriptorProto proto, int value) 265 { 266 proto.Options ??= new FileOptions(); 267 proto.Options.Features ??= new FeatureSet(); 268 SetTestFeature(proto.Options.Features, value); 269 } 270 SetTestFeature(DescriptorProto proto, int value)271 private static void SetTestFeature(DescriptorProto proto, int value) 272 { 273 proto.Options ??= new MessageOptions(); 274 proto.Options.Features ??= new FeatureSet(); 275 SetTestFeature(proto.Options.Features, value); 276 } 277 SetTestFeature(EnumDescriptorProto proto, int value)278 private static void SetTestFeature(EnumDescriptorProto proto, int value) 279 { 280 proto.Options ??= new EnumOptions(); 281 proto.Options.Features ??= new FeatureSet(); 282 SetTestFeature(proto.Options.Features, value); 283 } 284 SetTestFeature(EnumValueDescriptorProto proto, int value)285 private static void SetTestFeature(EnumValueDescriptorProto proto, int value) 286 { 287 proto.Options ??= new EnumValueOptions(); 288 proto.Options.Features ??= new FeatureSet(); 289 SetTestFeature(proto.Options.Features, value); 290 } 291 SetTestFeature(FieldDescriptorProto proto, int value)292 private static void SetTestFeature(FieldDescriptorProto proto, int value) 293 { 294 proto.Options ??= new FieldOptions(); 295 proto.Options.Features ??= new FeatureSet(); 296 SetTestFeature(proto.Options.Features, value); 297 } 298 SetTestFeature(ServiceDescriptorProto proto, int value)299 private static void SetTestFeature(ServiceDescriptorProto proto, int value) 300 { 301 proto.Options ??= new ServiceOptions(); 302 proto.Options.Features ??= new FeatureSet(); 303 SetTestFeature(proto.Options.Features, value); 304 } 305 SetTestFeature(OneofDescriptorProto proto, int value)306 private static void SetTestFeature(OneofDescriptorProto proto, int value) 307 { 308 proto.Options ??= new OneofOptions(); 309 proto.Options.Features ??= new FeatureSet(); 310 SetTestFeature(proto.Options.Features, value); 311 } 312 SetTestFeature(MethodDescriptorProto proto, int value)313 private static void SetTestFeature(MethodDescriptorProto proto, int value) 314 { 315 proto.Options ??= new MethodOptions(); 316 proto.Options.Features ??= new FeatureSet(); 317 SetTestFeature(proto.Options.Features, value); 318 } 319 SetTestFeature(FeatureSet features, int value)320 private static void SetTestFeature(FeatureSet features, int value) => 321 features.SetExtension(UnittestFeaturesExtensions.Test, 322 new TestFeatures { MultipleFeature = (Pb.EnumFeature)value }); 323 324 private static FileDescriptor Build(FileDescriptorProto fileProto) => 325 FileDescriptor.BuildFromByteStrings(new[] { fileProto.ToByteString() }, new ExtensionRegistry { UnittestFeaturesExtensions.Test })[0]; 326 CreateFileProto()327 private static FileDescriptorProto CreateFileProto() => new FileDescriptorProto 328 { 329 Name = "some/filename/some.proto", 330 Package = "proto2_unittest", 331 Edition = Edition._2023, 332 Syntax = "editions", 333 Extension = 334 { 335 new FieldDescriptorProto { Name = "top_extension", Number = 10, Type = Type.Int32, Label = Label.Optional, Extendee = ".proto2_unittest.TopMessage" } 336 }, 337 EnumType = 338 { 339 new EnumDescriptorProto { Name = "TopEnum", Value = { new EnumValueDescriptorProto { Name = "TOP_VALUE", Number = 0 } } } 340 }, 341 MessageType = 342 { 343 new DescriptorProto 344 { 345 Name = "TopMessage", 346 Field = 347 { 348 new FieldDescriptorProto { Name = "field", Number = 1, Type = Type.Int32, Label = Label.Optional }, 349 new FieldDescriptorProto { Name = "oneof_field", Number = 2, Type = Type.Int32, Label = Label.Optional, OneofIndex = 0 } 350 }, 351 Extension = 352 { 353 new FieldDescriptorProto { Name = "nested_extension", Number = 11, Type = Type.Int32, Label = Label.Optional, Extendee = ".proto2_unittest.TopMessage" } 354 }, 355 NestedType = 356 { 357 new DescriptorProto { Name = "NestedMessage" }, 358 }, 359 EnumType = 360 { 361 new EnumDescriptorProto { Name = "NestedEnum", Value = { new EnumValueDescriptorProto { Name = "NESTED_VALUE", Number = 0 } } } 362 }, 363 OneofDecl = { new OneofDescriptorProto { Name = "Oneof" } } 364 } 365 }, 366 Service = 367 { 368 new ServiceDescriptorProto 369 { 370 Name = "TestService", 371 Method = { new MethodDescriptorProto { Name = "CallMethod", InputType = ".proto2_unittest.TopMessage", OutputType = ".proto2_unittest.TopMessage" } } 372 } 373 } 374 }; 375 } 376