blob: 29a376e049dc3ffade4a1e418eacbc5592f18fa7 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001#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
33using System.Linq;
34using Google.Protobuf.TestProtos;
35using NUnit.Framework;
36using UnitTest.Issues.TestProtos;
37
38namespace Google.Protobuf.Reflection
39{
40 /// <summary>
41 /// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the
42 /// size doesn't warrant it. On the other hand, this makes me feel a bit dirty...)
43 /// </summary>
44 public class DescriptorsTest
45 {
46 [Test]
47 public void FileDescriptor()
48 {
49 FileDescriptor file = UnittestProto3Reflection.Descriptor;
50
Austin Schuh40c16522018-10-28 20:27:54 -070051 Assert.AreEqual("unittest_proto3.proto", file.Name);
52 Assert.AreEqual("protobuf_unittest3", file.Package);
Brian Silverman9c614bc2016-02-15 20:20:02 -050053
54 Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname);
Austin Schuh40c16522018-10-28 20:27:54 -070055 Assert.AreEqual("unittest_proto3.proto", file.Proto.Name);
Brian Silverman9c614bc2016-02-15 20:20:02 -050056
Austin Schuh40c16522018-10-28 20:27:54 -070057 // unittest_proto3.proto doesn't have any public imports, but unittest_import_proto3.proto does.
Brian Silverman9c614bc2016-02-15 20:20:02 -050058 Assert.AreEqual(0, file.PublicDependencies.Count);
59 Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.PublicDependencies.Count);
60 Assert.AreEqual(UnittestImportPublicProto3Reflection.Descriptor, UnittestImportProto3Reflection.Descriptor.PublicDependencies[0]);
61
62 Assert.AreEqual(1, file.Dependencies.Count);
63 Assert.AreEqual(UnittestImportProto3Reflection.Descriptor, file.Dependencies[0]);
64
65 MessageDescriptor messageType = TestAllTypes.Descriptor;
66 Assert.AreSame(typeof(TestAllTypes), messageType.ClrType);
67 Assert.AreSame(TestAllTypes.Parser, messageType.Parser);
68 Assert.AreEqual(messageType, file.MessageTypes[0]);
69 Assert.AreEqual(messageType, file.FindTypeByName<MessageDescriptor>("TestAllTypes"));
70 Assert.Null(file.FindTypeByName<MessageDescriptor>("NoSuchType"));
Austin Schuh40c16522018-10-28 20:27:54 -070071 Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest3.TestAllTypes"));
Brian Silverman9c614bc2016-02-15 20:20:02 -050072 for (int i = 0; i < file.MessageTypes.Count; i++)
73 {
74 Assert.AreEqual(i, file.MessageTypes[i].Index);
75 }
76
77 Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName<EnumDescriptor>("ForeignEnum"));
78 Assert.Null(file.FindTypeByName<EnumDescriptor>("NoSuchType"));
Austin Schuh40c16522018-10-28 20:27:54 -070079 Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest3.ForeignEnum"));
Brian Silverman9c614bc2016-02-15 20:20:02 -050080 Assert.AreEqual(1, UnittestImportProto3Reflection.Descriptor.EnumTypes.Count);
81 Assert.AreEqual("ImportEnum", UnittestImportProto3Reflection.Descriptor.EnumTypes[0].Name);
82 for (int i = 0; i < file.EnumTypes.Count; i++)
83 {
84 Assert.AreEqual(i, file.EnumTypes[i].Index);
85 }
86
87 Assert.AreEqual(10, file.SerializedData[0]);
88 }
89
90 [Test]
Austin Schuh40c16522018-10-28 20:27:54 -070091 public void FileDescriptor_NonRootPath()
92 {
93 // unittest_proto3.proto used to be in google/protobuf. Now it's in the C#-specific location,
94 // let's test something that's still in a directory.
95 FileDescriptor file = UnittestWellKnownTypesReflection.Descriptor;
96 Assert.AreEqual("google/protobuf/unittest_well_known_types.proto", file.Name);
97 Assert.AreEqual("protobuf_unittest", file.Package);
98 }
99
100 [Test]
Brian Silverman9c614bc2016-02-15 20:20:02 -0500101 public void MessageDescriptor()
102 {
103 MessageDescriptor messageType = TestAllTypes.Descriptor;
104 MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor;
105
106 Assert.AreEqual("TestAllTypes", messageType.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700107 Assert.AreEqual("protobuf_unittest3.TestAllTypes", messageType.FullName);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500108 Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File);
109 Assert.IsNull(messageType.ContainingType);
110 Assert.IsNull(messageType.Proto.Options);
111
112 Assert.AreEqual("TestAllTypes", messageType.Name);
113
114 Assert.AreEqual("NestedMessage", nestedType.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700115 Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedMessage", nestedType.FullName);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500116 Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
117 Assert.AreEqual(messageType, nestedType.ContainingType);
118
119 FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0];
120 Assert.AreEqual("single_int32", field.Name);
121 Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32"));
122 Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field"));
123 Assert.AreEqual(field, messageType.FindFieldByNumber(1));
124 Assert.Null(messageType.FindFieldByNumber(571283));
125 var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder();
126 for (int i = 0; i < fieldsInDeclarationOrder.Count; i++)
127 {
128 Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index);
129 }
130
131 Assert.AreEqual(nestedType, messageType.NestedTypes[0]);
132 Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage"));
133 Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType"));
134 for (int i = 0; i < messageType.NestedTypes.Count; i++)
135 {
136 Assert.AreEqual(i, messageType.NestedTypes[i].Index);
137 }
138
139 Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum"));
140 Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType"));
141 for (int i = 0; i < messageType.EnumTypes.Count; i++)
142 {
143 Assert.AreEqual(i, messageType.EnumTypes[i].Index);
144 }
145 }
146
147 [Test]
148 public void FieldDescriptor()
149 {
150 MessageDescriptor messageType = TestAllTypes.Descriptor;
151 FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32");
152 FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum");
153 FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message");
154
155 Assert.AreEqual("single_int32", primitiveField.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700156 Assert.AreEqual("protobuf_unittest3.TestAllTypes.single_int32",
Brian Silverman9c614bc2016-02-15 20:20:02 -0500157 primitiveField.FullName);
158 Assert.AreEqual(1, primitiveField.FieldNumber);
159 Assert.AreEqual(messageType, primitiveField.ContainingType);
160 Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File);
161 Assert.AreEqual(FieldType.Int32, primitiveField.FieldType);
162 Assert.IsNull(primitiveField.Proto.Options);
163
164 Assert.AreEqual("single_nested_enum", enumField.Name);
165 Assert.AreEqual(FieldType.Enum, enumField.FieldType);
166 // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType);
167
168 Assert.AreEqual("single_foreign_message", messageField.Name);
169 Assert.AreEqual(FieldType.Message, messageField.FieldType);
170 Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType);
171 }
172
173 [Test]
174 public void FieldDescriptorLabel()
175 {
176 FieldDescriptor singleField =
177 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32");
178 FieldDescriptor repeatedField =
179 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32");
180
181 Assert.IsFalse(singleField.IsRepeated);
182 Assert.IsTrue(repeatedField.IsRepeated);
183 }
184
185 [Test]
186 public void EnumDescriptor()
187 {
188 // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor
189 EnumDescriptor enumType = UnittestProto3Reflection.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum");
190 EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum");
191
192 Assert.AreEqual("ForeignEnum", enumType.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700193 Assert.AreEqual("protobuf_unittest3.ForeignEnum", enumType.FullName);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500194 Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File);
195 Assert.Null(enumType.ContainingType);
196 Assert.Null(enumType.Proto.Options);
197
198 Assert.AreEqual("NestedEnum", nestedType.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700199 Assert.AreEqual("protobuf_unittest3.TestAllTypes.NestedEnum",
Brian Silverman9c614bc2016-02-15 20:20:02 -0500200 nestedType.FullName);
201 Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File);
202 Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType);
203
204 EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO");
205 Assert.AreEqual(value, enumType.Values[1]);
206 Assert.AreEqual("FOREIGN_FOO", value.Name);
207 Assert.AreEqual(4, value.Number);
Austin Schuh40c16522018-10-28 20:27:54 -0700208 Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500209 Assert.AreEqual(value, enumType.FindValueByNumber(4));
210 Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE"));
211 for (int i = 0; i < enumType.Values.Count; i++)
212 {
213 Assert.AreEqual(i, enumType.Values[i].Index);
214 }
215 }
216
217 [Test]
218 public void OneofDescriptor()
219 {
220 OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field");
221 Assert.AreEqual("oneof_field", descriptor.Name);
Austin Schuh40c16522018-10-28 20:27:54 -0700222 Assert.AreEqual("protobuf_unittest3.TestAllTypes.oneof_field", descriptor.FullName);
Brian Silverman9c614bc2016-02-15 20:20:02 -0500223
224 var expectedFields = new[] {
225 TestAllTypes.OneofBytesFieldNumber,
226 TestAllTypes.OneofNestedMessageFieldNumber,
227 TestAllTypes.OneofStringFieldNumber,
228 TestAllTypes.OneofUint32FieldNumber }
229 .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber))
230 .ToList();
231 foreach (var field in expectedFields)
232 {
233 Assert.AreSame(descriptor, field.ContainingOneof);
234 }
235
236 CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields);
237 }
238
239 [Test]
240 public void MapEntryMessageDescriptor()
241 {
242 var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0];
243 Assert.IsNull(descriptor.Parser);
244 Assert.IsNull(descriptor.ClrType);
245 Assert.IsNull(descriptor.Fields[1].Accessor);
246 }
247
248 // From TestFieldOrdering:
249 // string my_string = 11;
250 // int64 my_int = 1;
251 // float my_float = 101;
252 // NestedMessage single_nested_message = 200;
253 [Test]
254 public void FieldListOrderings()
255 {
256 var fields = TestFieldOrderings.Descriptor.Fields;
257 Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber));
258 Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber));
259 }
260
261
262 [Test]
263 public void DescriptorProtoFileDescriptor()
264 {
265 var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor;
266 Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name);
267 }
268 }
269}