• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 // Protocol Buffers - Google's data interchange format
3 // Copyright 2008 Google Inc.  All rights reserved.
4 // https://developers.google.com/protocol-buffers/
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
8 // met:
9 //
10 //     * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 //     * Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following disclaimer
14 // in the documentation and/or other materials provided with the
15 // distribution.
16 //     * Neither the name of Google Inc. nor the names of its
17 // contributors may be used to endorse or promote products derived from
18 // this software without specific prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #endregion
32 
33 using Google.Protobuf.TestProtos;
34 using NUnit.Framework;
35 using ProtobufUnittest;
36 using System;
37 using System.Collections.Generic;
38 using System.IO;
39 using System.Linq;
40 using UnitTest.Issues.TestProtos;
41 
42 namespace Google.Protobuf.Reflection
43 {
44     /// <summary>
45     /// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the
46     /// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...)
47     /// </summary>
48     public class DescriptorsTest
49     {
50         [Test]
FileDescriptor_GeneratedCode()51         public void FileDescriptor_GeneratedCode()
52         {
53             TestFileDescriptor(
54                 UnittestProto3Reflection.Descriptor,
55                 UnittestImportProto3Reflection.Descriptor,
56                 UnittestImportPublicProto3Reflection.Descriptor);
57         }
58 
59         [Test]
FileDescriptor_BuildFromByteStrings()60         public void FileDescriptor_BuildFromByteStrings()
61         {
62             // The descriptors have to be supplied in an order such that all the
63             // dependencies come before the descriptors depending on them.
64             var descriptorData = new List<ByteString>
65             {
66                 UnittestImportPublicProto3Reflection.Descriptor.SerializedData,
67                 UnittestImportProto3Reflection.Descriptor.SerializedData,
68                 UnittestProto3Reflection.Descriptor.SerializedData
69             };
70             var converted = FileDescriptor.BuildFromByteStrings(descriptorData);
71             Assert.AreEqual(3, converted.Count);
72             TestFileDescriptor(converted[2], converted[1], converted[0]);
73         }
74 
75         [Test]
FileDescriptor_BuildFromByteStrings_WithExtensionRegistry()76         public void FileDescriptor_BuildFromByteStrings_WithExtensionRegistry()
77         {
78             var extension = UnittestCustomOptionsProto3Extensions.MessageOpt1;
79 
80             var byteStrings = new[]
81             {
82                 DescriptorReflection.Descriptor.Proto.ToByteString(),
83                 UnittestCustomOptionsProto3Reflection.Descriptor.Proto.ToByteString()
84             };
85             var registry = new ExtensionRegistry { extension };
86 
87             var descriptor = FileDescriptor.BuildFromByteStrings(byteStrings, registry).Last();
88             var message = descriptor.MessageTypes.Single(t => t.Name == nameof(TestMessageWithCustomOptions));
89             var extensionValue = message.GetOptions().GetExtension(extension);
90             Assert.AreEqual(-56, extensionValue);
91         }
92 
TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile)93         private void TestFileDescriptor(FileDescriptor file, FileDescriptor importedFile, FileDescriptor importedPublicFile)
94         {
95             Assert.AreEqual("unittest_proto3.proto", file.Name);
96             Assert.AreEqual("protobuf_unittest3", file.Package);
97 
98             Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
99             Assert.AreEqual("unittest_proto3.proto", file.Proto.Name);
100 
101             // unittest_proto3.proto doesn't have any public imports, but unittest_import_proto3.proto does.
102             Assert.AreEqual(0, file.PublicDependencies.Count);
103             Assert.AreEqual(1, importedFile.PublicDependencies.Count);
104             Assert.AreEqual(importedPublicFile, importedFile.PublicDependencies[0]);
105 
106             Assert.AreEqual(1, file.Dependencies.Count);
107             Assert.AreEqual(importedFile, file.Dependencies[0]);
108 
109             Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
110             Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest3.TestAllTypes"));
111             for (int i = 0; i < file.MessageTypes.Count; i++)
112             {
113                 Assert.AreEqual(i, file.MessageTypes[i].Index);
114             }
115 
116             Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
117             Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
118             Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest3.ForeignEnum"));
119             Assert.AreEqual(1, importedFile.EnumTypes.Count);
120             Assert.AreEqual("ImportEnum", importedFile.EnumTypes[0].Name);
121             for (int i = 0; i < file.EnumTypes.Count; i++)
122             {
123                 Assert.AreEqual(i, file.EnumTypes[i].Index);
124             }
125 
126             Assert.AreEqual(10, file.SerializedData[0]);
127             TestDescriptorToProto(file.ToProto, file.Proto);
128         }
129 
130         [Test]
FileDescriptor_NonRootPath()131         public void FileDescriptor_NonRootPath()
132         {
133             // unittest_proto3.proto used to be in google/protobuf. Now it's in the C#-specific location,
134             // let's test something that's still in a directory.
135             FileDescriptor file = UnittestWellKnownTypesReflection.Descriptor;
136             Assert.AreEqual("google/protobuf/unittest_well_known_types.proto", file.Name);
137             Assert.AreEqual("protobuf_unittest", file.Package);
138         }
139 
140         [Test]
FileDescriptor_BuildFromByteStrings_MissingDependency()141         public void FileDescriptor_BuildFromByteStrings_MissingDependency()
142         {
143             var descriptorData = new List<ByteString>
144             {
145                 UnittestImportProto3Reflection.Descriptor.SerializedData,
146                 UnittestProto3Reflection.Descriptor.SerializedData,
147             };
148             // This will fail, because we're missing UnittestImportPublicProto3Reflection
149             Assert.Throws<ArgumentException>(() => FileDescriptor.BuildFromByteStrings(descriptorData));
150         }
151 
152         [Test]
FileDescriptor_BuildFromByteStrings_DuplicateNames()153         public void FileDescriptor_BuildFromByteStrings_DuplicateNames()
154         {
155             var descriptorData = new List<ByteString>
156             {
157                 UnittestImportPublicProto3Reflection.Descriptor.SerializedData,
158                 UnittestImportPublicProto3Reflection.Descriptor.SerializedData,
159             };
160             // This will fail due to the same name being used twice
161             Assert.Throws<ArgumentException>(() => FileDescriptor.BuildFromByteStrings(descriptorData));
162         }
163 
164         [Test]
FileDescriptor_BuildFromByteStrings_IncorrectOrder()165         public void FileDescriptor_BuildFromByteStrings_IncorrectOrder()
166         {
167             var descriptorData = new List<ByteString>
168             {
169                 UnittestProto3Reflection.Descriptor.SerializedData,
170                 UnittestImportPublicProto3Reflection.Descriptor.SerializedData,
171                 UnittestImportProto3Reflection.Descriptor.SerializedData
172             };
173             // This will fail, because the dependencies should come first
174             Assert.Throws<ArgumentException>(() => FileDescriptor.BuildFromByteStrings(descriptorData));
175 
176         }
177 
178         [Test]
MessageDescriptorFromGeneratedCodeFileDescriptor()179         public void MessageDescriptorFromGeneratedCodeFileDescriptor()
180         {
181             var file = UnittestProto3Reflection.Descriptor;
182 
183             MessageDescriptor messageType = TestAllTypes.Descriptor;
184             Assert.AreSame(typeof(TestAllTypes), messageType.ClrType);
185             Assert.AreSame(TestAllTypes.Parser, messageType.Parser);
186             Assert.AreEqual(messageType, file.MessageTypes[0]);
187             Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
188         }
189 
190         [Test]
MessageDescriptor()191         public void MessageDescriptor()
192         {
193             MessageDescriptor messageType = TestAllTypes.Descriptor;
194             MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
195 
196             Assert.AreEqual("TestAllTypes", messageType.Name);
197             Assert.AreEqual("protobuf_unittest3.TestAllTypes", messageType.FullName);
198             Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File);
199             Assert.IsNull(messageType.ContainingType);
200             Assert.IsNull(messageType.Proto.Options);
201 
202             Assert.AreEqual("TestAllTypes", messageType.Name);
203 
204             Assert.AreEqual("NestedMessage", nestedType.Name);
205             Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedMessage", nestedType.FullName);
206             Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
207             Assert.AreEqual(messageType, nestedType.ContainingType);
208 
209             FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0];
210             Assert.AreEqual("single_int32", field.Name);
211             Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32"));
212             Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
213             Assert.AreEqual(field, messageType.FindFieldByNumber(1));
214             Assert.Null(messageType.FindFieldByNumber(571283));
215             var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder();
216             for (int i = 0; i < fieldsInDeclarationOrder.Count; i++)
217             {
218                 Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index);
219             }
220 
221             Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
222             Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
223             Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType"));
224             for (int i = 0; i < messageType.NestedTypes.Count; i++)
225             {
226                 Assert.AreEqual(i, messageType.NestedTypes[i].Index);
227             }
228 
229             Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum"));
230             Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType"));
231             for (int i = 0; i < messageType.EnumTypes.Count; i++)
232             {
233                 Assert.AreEqual(i, messageType.EnumTypes[i].Index);
234             }
235             TestDescriptorToProto(messageType.ToProto, messageType.Proto);
236         }
237 
238         [Test]
FieldDescriptor_GeneratedCode()239         public void FieldDescriptor_GeneratedCode()
240         {
241             TestFieldDescriptor(UnittestProto3Reflection.Descriptor, TestAllTypes.Descriptor, ForeignMessage.Descriptor, ImportMessage.Descriptor);
242         }
243 
244         [Test]
FieldDescriptor_BuildFromByteStrings()245         public void FieldDescriptor_BuildFromByteStrings()
246         {
247             // The descriptors have to be supplied in an order such that all the
248             // dependencies come before the descriptors depending on them.
249             var descriptorData = new List<ByteString>
250             {
251                 UnittestImportPublicProto3Reflection.Descriptor.SerializedData,
252                 UnittestImportProto3Reflection.Descriptor.SerializedData,
253                 UnittestProto3Reflection.Descriptor.SerializedData
254             };
255             var converted = FileDescriptor.BuildFromByteStrings(descriptorData);
256             TestFieldDescriptor(
257                 converted[2],
258                 converted[2].FindTypeByName<MessageDescriptor>("TestAllTypes"),
259                 converted[2].FindTypeByName<MessageDescriptor>("ForeignMessage"),
260                 converted[1].FindTypeByName<MessageDescriptor>("ImportMessage"));
261         }
262 
TestFieldDescriptor( FileDescriptor unitTestProto3Descriptor, MessageDescriptor testAllTypesDescriptor, MessageDescriptor foreignMessageDescriptor, MessageDescriptor importMessageDescriptor)263         public void TestFieldDescriptor(
264             FileDescriptor unitTestProto3Descriptor,
265             MessageDescriptor testAllTypesDescriptor,
266             MessageDescriptor foreignMessageDescriptor,
267             MessageDescriptor importMessageDescriptor)
268         {
269             FieldDescriptor primitiveField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_int32");
270             FieldDescriptor enumField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_nested_enum");
271             FieldDescriptor foreignMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_foreign_message");
272             FieldDescriptor importMessageField = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("single_import_message");
273             FieldDescriptor fieldInOneof = testAllTypesDescriptor.FindDescriptor<FieldDescriptor>("oneof_string");
274 
275             Assert.AreEqual("single_int32", primitiveField.Name);
276             Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32",
277                             primitiveField.FullName);
278             Assert.AreEqual(1, primitiveField.FieldNumber);
279             Assert.AreEqual(testAllTypesDescriptor, primitiveField.ContainingType);
280             Assert.AreEqual(unitTestProto3Descriptor, primitiveField.File);
281             Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
282             Assert.IsNull(primitiveField.Proto.Options);
283 
284             Assert.AreEqual("single_nested_enum", enumField.Name);
285             Assert.AreEqual(FieldType.Enum, enumField.FieldType);
286             Assert.AreEqual(testAllTypesDescriptor.EnumTypes[0], enumField.EnumType);
287 
288             Assert.AreEqual("single_foreign_message", foreignMessageField.Name);
289             Assert.AreEqual(FieldType.Message, foreignMessageField.FieldType);
290             Assert.AreEqual(foreignMessageDescriptor, foreignMessageField.MessageType);
291 
292             Assert.AreEqual("single_import_message", importMessageField.Name);
293             Assert.AreEqual(FieldType.Message, importMessageField.FieldType);
294             Assert.AreEqual(importMessageDescriptor, importMessageField.MessageType);
295 
296             // For a field in a regular onoef, ContainingOneof and RealContainingOneof should be the same.
297             Assert.AreEqual("oneof_field", fieldInOneof.ContainingOneof.Name);
298             Assert.AreSame(fieldInOneof.ContainingOneof, fieldInOneof.RealContainingOneof);
299 
300             TestDescriptorToProto(primitiveField.ToProto, primitiveField.Proto);
301             TestDescriptorToProto(enumField.ToProto, enumField.Proto);
302             TestDescriptorToProto(foreignMessageField.ToProto, foreignMessageField.Proto);
303             TestDescriptorToProto(fieldInOneof.ToProto, fieldInOneof.Proto);
304         }
305 
306         [Test]
FieldDescriptorLabel()307         public void FieldDescriptorLabel()
308         {
309             FieldDescriptor singleField =
310                 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32");
311             FieldDescriptor repeatedField =
312                 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
313 
314             Assert.IsFalse(singleField.IsRepeated);
315             Assert.IsTrue(repeatedField.IsRepeated);
316         }
317 
318         [Test]
EnumDescriptor()319         public void EnumDescriptor()
320         {
321             // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor
322             EnumDescriptor enumType = UnittestProto3Reflection.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum");
323             EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
324 
325             Assert.AreEqual("ForeignEnum", enumType.Name);
326             Assert.AreEqual("protobuf_unittest3.ForeignEnum", enumType.FullName);
327             Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File);
328             Assert.Null(enumType.ContainingType);
329             Assert.Null(enumType.Proto.Options);
330 
331             Assert.AreEqual("NestedEnum", nestedType.Name);
332             Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedEnum",
333                             nestedType.FullName);
334             Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
335             Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
336 
337             EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
338             Assert.AreEqual(value, enumType.Values[1]);
339             Assert.AreEqual("FOREIGN_FOO", value.Name);
340             Assert.AreEqual(4, value.Number);
341             Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number);
342             Assert.AreEqual(value, enumType.FindValueByNumber(4));
343             Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
344             for (int i = 0; i < enumType.Values.Count; i++)
345             {
346                 Assert.AreEqual(i, enumType.Values[i].Index);
347             }
348             TestDescriptorToProto(enumType.ToProto, enumType.Proto);
349             TestDescriptorToProto(nestedType.ToProto, nestedType.Proto);
350         }
351 
352         [Test]
OneofDescriptor()353         public void OneofDescriptor()
354         {
355             OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
356             Assert.IsFalse(descriptor.IsSynthetic);
357             Assert.AreEqual("oneof_field", descriptor.Name);
358             Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName);
359 
360             var expectedFields = new[] {
361                 TestAllTypes.OneofBytesFieldNumber,
362                 TestAllTypes.OneofNestedMessageFieldNumber,
363                 TestAllTypes.OneofStringFieldNumber,
364                 TestAllTypes.OneofUint32FieldNumber }
365                 .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
366                 .ToList();
367             foreach (var field in expectedFields)
368             {
369                 Assert.AreSame(descriptor, field.ContainingOneof);
370             }
371 
372             CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
373             TestDescriptorToProto(descriptor.ToProto, descriptor.Proto);
374         }
375 
376         [Test]
MapEntryMessageDescriptor()377         public void MapEntryMessageDescriptor()
378         {
379             var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0];
380             Assert.IsNull(descriptor.Parser);
381             Assert.IsNull(descriptor.ClrType);
382             Assert.IsNull(descriptor.Fields[1].Accessor);
383             TestDescriptorToProto(descriptor.ToProto, descriptor.Proto);
384         }
385 
386         // From TestFieldOrdering:
387         // string my_string = 11;
388         // int64 my_int = 1;
389         // float my_float = 101;
390         // NestedMessage single_nested_message = 200;
391         [Test]
FieldListOrderings()392         public void FieldListOrderings()
393         {
394             var fields = TestFieldOrderings.Descriptor.Fields;
395             Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber));
396             Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber));
397         }
398 
399 
400         [Test]
DescriptorProtoFileDescriptor()401         public void DescriptorProtoFileDescriptor()
402         {
403             var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor;
404             Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name);
405             TestDescriptorToProto(descriptor.ToProto, descriptor.Proto);
406         }
407 
408         [Test]
DescriptorImportingExtensionsFromOldCodeGen()409         public void DescriptorImportingExtensionsFromOldCodeGen()
410         {
411             // The extension collection includes a null extension. There's not a lot we can do about that
412             // in itself, as the old generator didn't provide us the extension information.
413             var extensions = TestProtos.OldGenerator.OldExtensions2Reflection.Descriptor.Extensions;
414             Assert.AreEqual(1, extensions.UnorderedExtensions.Count);
415             // Note: this assertion is present so that it will fail if OldExtensions2 is regenerated
416             // with a new generator.
417             Assert.Null(extensions.UnorderedExtensions[0].Extension);
418 
419             // ... but we can make sure we at least don't cause a failure when retrieving descriptors.
420             // In particular, old_extensions1.proto imports old_extensions2.proto, and this used to cause
421             // an execution-time failure.
422             var importingDescriptor = TestProtos.OldGenerator.OldExtensions1Reflection.Descriptor;
423             Assert.NotNull(importingDescriptor);
424         }
425 
426         [Test]
Proto3OptionalDescriptors()427         public void Proto3OptionalDescriptors()
428         {
429             var descriptor = TestProto3Optional.Descriptor;
430             var field = descriptor.Fields[TestProto3Optional.OptionalInt32FieldNumber];
431             Assert.NotNull(field.ContainingOneof);
432             Assert.IsTrue(field.ContainingOneof.IsSynthetic);
433             Assert.Null(field.RealContainingOneof);
434         }
435 
436 
437         [Test]
SyntheticOneofReflection()438         public void SyntheticOneofReflection()
439         {
440             // Expect every oneof in TestProto3Optional to be synthetic
441             var proto3OptionalDescriptor = TestProto3Optional.Descriptor;
442             Assert.AreEqual(0, proto3OptionalDescriptor.RealOneofCount);
443             foreach (var oneof in proto3OptionalDescriptor.Oneofs)
444             {
445                 Assert.True(oneof.IsSynthetic);
446             }
447 
448             // Expect no oneof in the original proto3 unit test file to be synthetic.
449             foreach (var descriptor in ProtobufTestMessages.Proto3.TestMessagesProto3Reflection.Descriptor.MessageTypes)
450             {
451                 Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
452                 foreach (var oneof in descriptor.Oneofs)
453                 {
454                     Assert.False(oneof.IsSynthetic);
455                 }
456             }
457 
458             // Expect no oneof in the original proto2 unit test file to be synthetic.
459             foreach (var descriptor in ProtobufTestMessages.Proto2.TestMessagesProto2Reflection.Descriptor.MessageTypes)
460             {
461                 Assert.AreEqual(descriptor.Oneofs.Count, descriptor.RealOneofCount);
462                 foreach (var oneof in descriptor.Oneofs)
463                 {
464                     Assert.False(oneof.IsSynthetic);
465                 }
466             }
467         }
468 
TestDescriptorToProto(Func<IMessage> toProtoFunction, IMessage expectedProto)469         private static void TestDescriptorToProto(Func<IMessage> toProtoFunction, IMessage expectedProto)
470         {
471             var clone1 = toProtoFunction();
472             var clone2 = toProtoFunction();
473             Assert.AreNotSame(clone1, clone2);
474             Assert.AreNotSame(clone1, expectedProto);
475             Assert.AreNotSame(clone2, expectedProto);
476 
477             Assert.AreEqual(clone1, clone2);
478             Assert.AreEqual(clone1, expectedProto);
479         }
480     }
481 }
482