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 System.Linq; 34 using Google.Protobuf.TestProtos; 35 using NUnit.Framework; 36 using UnitTest.Issues.TestProtos; 37 38 namespace 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] FileDescriptor()47 public void FileDescriptor() 48 { 49 FileDescriptor file = UnittestProto3Reflection.Descriptor; 50 51 Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); 52 Assert.AreEqual("protobuf_unittest", file.Package); 53 54 Assert.AreEqual("UnittestProto", file.Proto.Options.JavaOuterClassname); 55 Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); 56 57 // unittest.proto doesn't have any public imports, but unittest_import.proto does. 58 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")); 71 Assert.Null(file.FindTypeByName<MessageDescriptor>("protobuf_unittest.TestAllTypes")); 72 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")); 79 Assert.Null(file.FindTypeByName<EnumDescriptor>("protobuf_unittest.ForeignEnum")); 80 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] MessageDescriptor()91 public void MessageDescriptor() 92 { 93 MessageDescriptor messageType = TestAllTypes.Descriptor; 94 MessageDescriptor nestedType = TestAllTypes.Types.NestedMessage.Descriptor; 95 96 Assert.AreEqual("TestAllTypes", messageType.Name); 97 Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); 98 Assert.AreEqual(UnittestProto3Reflection.Descriptor, messageType.File); 99 Assert.IsNull(messageType.ContainingType); 100 Assert.IsNull(messageType.Proto.Options); 101 102 Assert.AreEqual("TestAllTypes", messageType.Name); 103 104 Assert.AreEqual("NestedMessage", nestedType.Name); 105 Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); 106 Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); 107 Assert.AreEqual(messageType, nestedType.ContainingType); 108 109 FieldDescriptor field = messageType.Fields.InDeclarationOrder()[0]; 110 Assert.AreEqual("single_int32", field.Name); 111 Assert.AreEqual(field, messageType.FindDescriptor<FieldDescriptor>("single_int32")); 112 Assert.Null(messageType.FindDescriptor<FieldDescriptor>("no_such_field")); 113 Assert.AreEqual(field, messageType.FindFieldByNumber(1)); 114 Assert.Null(messageType.FindFieldByNumber(571283)); 115 var fieldsInDeclarationOrder = messageType.Fields.InDeclarationOrder(); 116 for (int i = 0; i < fieldsInDeclarationOrder.Count; i++) 117 { 118 Assert.AreEqual(i, fieldsInDeclarationOrder[i].Index); 119 } 120 121 Assert.AreEqual(nestedType, messageType.NestedTypes[0]); 122 Assert.AreEqual(nestedType, messageType.FindDescriptor<MessageDescriptor>("NestedMessage")); 123 Assert.Null(messageType.FindDescriptor<MessageDescriptor>("NoSuchType")); 124 for (int i = 0; i < messageType.NestedTypes.Count; i++) 125 { 126 Assert.AreEqual(i, messageType.NestedTypes[i].Index); 127 } 128 129 Assert.AreEqual(messageType.EnumTypes[0], messageType.FindDescriptor<EnumDescriptor>("NestedEnum")); 130 Assert.Null(messageType.FindDescriptor<EnumDescriptor>("NoSuchType")); 131 for (int i = 0; i < messageType.EnumTypes.Count; i++) 132 { 133 Assert.AreEqual(i, messageType.EnumTypes[i].Index); 134 } 135 } 136 137 [Test] FieldDescriptor()138 public void FieldDescriptor() 139 { 140 MessageDescriptor messageType = TestAllTypes.Descriptor; 141 FieldDescriptor primitiveField = messageType.FindDescriptor<FieldDescriptor>("single_int32"); 142 FieldDescriptor enumField = messageType.FindDescriptor<FieldDescriptor>("single_nested_enum"); 143 FieldDescriptor messageField = messageType.FindDescriptor<FieldDescriptor>("single_foreign_message"); 144 145 Assert.AreEqual("single_int32", primitiveField.Name); 146 Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", 147 primitiveField.FullName); 148 Assert.AreEqual(1, primitiveField.FieldNumber); 149 Assert.AreEqual(messageType, primitiveField.ContainingType); 150 Assert.AreEqual(UnittestProto3Reflection.Descriptor, primitiveField.File); 151 Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); 152 Assert.IsNull(primitiveField.Proto.Options); 153 154 Assert.AreEqual("single_nested_enum", enumField.Name); 155 Assert.AreEqual(FieldType.Enum, enumField.FieldType); 156 // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); 157 158 Assert.AreEqual("single_foreign_message", messageField.Name); 159 Assert.AreEqual(FieldType.Message, messageField.FieldType); 160 Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); 161 } 162 163 [Test] FieldDescriptorLabel()164 public void FieldDescriptorLabel() 165 { 166 FieldDescriptor singleField = 167 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("single_int32"); 168 FieldDescriptor repeatedField = 169 TestAllTypes.Descriptor.FindDescriptor<FieldDescriptor>("repeated_int32"); 170 171 Assert.IsFalse(singleField.IsRepeated); 172 Assert.IsTrue(repeatedField.IsRepeated); 173 } 174 175 [Test] EnumDescriptor()176 public void EnumDescriptor() 177 { 178 // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor 179 EnumDescriptor enumType = UnittestProto3Reflection.Descriptor.FindTypeByName<EnumDescriptor>("ForeignEnum"); 180 EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor<EnumDescriptor>("NestedEnum"); 181 182 Assert.AreEqual("ForeignEnum", enumType.Name); 183 Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); 184 Assert.AreEqual(UnittestProto3Reflection.Descriptor, enumType.File); 185 Assert.Null(enumType.ContainingType); 186 Assert.Null(enumType.Proto.Options); 187 188 Assert.AreEqual("NestedEnum", nestedType.Name); 189 Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", 190 nestedType.FullName); 191 Assert.AreEqual(UnittestProto3Reflection.Descriptor, nestedType.File); 192 Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); 193 194 EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO"); 195 Assert.AreEqual(value, enumType.Values[1]); 196 Assert.AreEqual("FOREIGN_FOO", value.Name); 197 Assert.AreEqual(4, value.Number); 198 Assert.AreEqual((int) ForeignEnum.ForeignFoo, value.Number); 199 Assert.AreEqual(value, enumType.FindValueByNumber(4)); 200 Assert.Null(enumType.FindValueByName("NO_SUCH_VALUE")); 201 for (int i = 0; i < enumType.Values.Count; i++) 202 { 203 Assert.AreEqual(i, enumType.Values[i].Index); 204 } 205 } 206 207 [Test] OneofDescriptor()208 public void OneofDescriptor() 209 { 210 OneofDescriptor descriptor = TestAllTypes.Descriptor.FindDescriptor<OneofDescriptor>("oneof_field"); 211 Assert.AreEqual("oneof_field", descriptor.Name); 212 Assert.AreEqual("protobuf_unittest.TestAllTypes.oneof_field", descriptor.FullName); 213 214 var expectedFields = new[] { 215 TestAllTypes.OneofBytesFieldNumber, 216 TestAllTypes.OneofNestedMessageFieldNumber, 217 TestAllTypes.OneofStringFieldNumber, 218 TestAllTypes.OneofUint32FieldNumber } 219 .Select(fieldNumber => TestAllTypes.Descriptor.FindFieldByNumber(fieldNumber)) 220 .ToList(); 221 foreach (var field in expectedFields) 222 { 223 Assert.AreSame(descriptor, field.ContainingOneof); 224 } 225 226 CollectionAssert.AreEquivalent(expectedFields, descriptor.Fields); 227 } 228 229 [Test] MapEntryMessageDescriptor()230 public void MapEntryMessageDescriptor() 231 { 232 var descriptor = MapWellKnownTypes.Descriptor.NestedTypes[0]; 233 Assert.IsNull(descriptor.Parser); 234 Assert.IsNull(descriptor.ClrType); 235 Assert.IsNull(descriptor.Fields[1].Accessor); 236 } 237 238 // From TestFieldOrdering: 239 // string my_string = 11; 240 // int64 my_int = 1; 241 // float my_float = 101; 242 // NestedMessage single_nested_message = 200; 243 [Test] FieldListOrderings()244 public void FieldListOrderings() 245 { 246 var fields = TestFieldOrderings.Descriptor.Fields; 247 Assert.AreEqual(new[] { 11, 1, 101, 200 }, fields.InDeclarationOrder().Select(x => x.FieldNumber)); 248 Assert.AreEqual(new[] { 1, 11, 101, 200 }, fields.InFieldNumberOrder().Select(x => x.FieldNumber)); 249 } 250 251 252 [Test] DescriptorProtoFileDescriptor()253 public void DescriptorProtoFileDescriptor() 254 { 255 var descriptor = Google.Protobuf.Reflection.FileDescriptor.DescriptorProtoFileDescriptor; 256 Assert.AreEqual("google/protobuf/descriptor.proto", descriptor.Name); 257 } 258 } 259 } 260