1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3// https://developers.google.com/protocol-buffers/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9//     * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11//     * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15//     * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31#import "GPBTestUtilities.h"
32
33#import <objc/runtime.h>
34
35#import "GPBDescriptor_PackagePrivate.h"
36#import "google/protobuf/Unittest.pbobjc.h"
37#import "google/protobuf/UnittestObjc.pbobjc.h"
38#import "google/protobuf/Descriptor.pbobjc.h"
39
40@interface DescriptorTests : GPBTestCase
41@end
42
43@implementation DescriptorTests
44
45- (void)testDescriptor_containingType {
46  GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
47  GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
48  XCTAssertNil(testAllTypesDesc.containingType);
49  XCTAssertNotNil(nestedMessageDesc.containingType);
50  XCTAssertEqual(nestedMessageDesc.containingType, testAllTypesDesc);  // Ptr comparison
51}
52
53- (void)testDescriptor_fullName {
54  GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
55  XCTAssertEqualObjects(testAllTypesDesc.fullName, @"protobuf_unittest.TestAllTypes");
56  GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
57  XCTAssertEqualObjects(nestedMessageDesc.fullName, @"protobuf_unittest.TestAllTypes.NestedMessage");
58
59  // Prefixes removed.
60  GPBDescriptor *descDesc = [GPBDescriptorProto descriptor];
61  XCTAssertEqualObjects(descDesc.fullName, @"google.protobuf.DescriptorProto");
62  GPBDescriptor *descExtRngDesc = [GPBDescriptorProto_ExtensionRange descriptor];
63  XCTAssertEqualObjects(descExtRngDesc.fullName, @"google.protobuf.DescriptorProto.ExtensionRange");
64
65  // Things that get "_Class" added.
66  GPBDescriptor *pointDesc = [Point_Class descriptor];
67  XCTAssertEqualObjects(pointDesc.fullName, @"protobuf_unittest.Point");
68  GPBDescriptor *pointRectDesc = [Point_Rect descriptor];
69  XCTAssertEqualObjects(pointRectDesc.fullName, @"protobuf_unittest.Point.Rect");
70}
71
72- (void)testFieldDescriptor {
73  GPBDescriptor *descriptor = [TestAllTypes descriptor];
74
75  // Nested Enum
76  GPBFieldDescriptor *fieldDescriptorWithName =
77      [descriptor fieldWithName:@"optionalNestedEnum"];
78  XCTAssertNotNil(fieldDescriptorWithName);
79  GPBFieldDescriptor *fieldDescriptorWithNumber =
80      [descriptor fieldWithNumber:21];
81  XCTAssertNotNil(fieldDescriptorWithNumber);
82  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
83  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
84  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
85                        @"TestAllTypes_NestedEnum");
86  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
87  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
88
89  // Foreign Enum
90  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"];
91  XCTAssertNotNil(fieldDescriptorWithName);
92  fieldDescriptorWithNumber = [descriptor fieldWithNumber:22];
93  XCTAssertNotNil(fieldDescriptorWithNumber);
94  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
95  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
96  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
97                        @"ForeignEnum");
98  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
99  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
100
101  // Import Enum
102  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"];
103  XCTAssertNotNil(fieldDescriptorWithName);
104  fieldDescriptorWithNumber = [descriptor fieldWithNumber:23];
105  XCTAssertNotNil(fieldDescriptorWithNumber);
106  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
107  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
108  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
109                        @"ImportEnum");
110  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
111  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
112
113  // Nested Message
114  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"];
115  XCTAssertNotNil(fieldDescriptorWithName);
116  fieldDescriptorWithNumber = [descriptor fieldWithNumber:18];
117  XCTAssertNotNil(fieldDescriptorWithNumber);
118  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
119  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
120  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
121  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
122
123  // Foreign Message
124  fieldDescriptorWithName =
125      [descriptor fieldWithName:@"optionalForeignMessage"];
126  XCTAssertNotNil(fieldDescriptorWithName);
127  fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
128  XCTAssertNotNil(fieldDescriptorWithNumber);
129  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
130  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
131  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
132  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
133
134  // Import Message
135  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"];
136  XCTAssertNotNil(fieldDescriptorWithName);
137  fieldDescriptorWithNumber = [descriptor fieldWithNumber:20];
138  XCTAssertNotNil(fieldDescriptorWithNumber);
139  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
140  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
141  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
142  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
143
144  // Some failed lookups.
145  XCTAssertNil([descriptor fieldWithName:@"NOT THERE"]);
146  XCTAssertNil([descriptor fieldWithNumber:9876543]);
147}
148
149- (void)testEnumDescriptor {
150  GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
151
152  NSString *enumName = [descriptor enumNameForValue:1];
153  XCTAssertNotNil(enumName);
154  int32_t value;
155  XCTAssertTrue(
156      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
157  XCTAssertTrue(
158      [descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
159  XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
160
161  enumName = [descriptor enumNameForValue:2];
162  XCTAssertNotNil(enumName);
163  XCTAssertTrue(
164      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
165  XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
166
167  enumName = [descriptor enumNameForValue:3];
168  XCTAssertNotNil(enumName);
169  XCTAssertTrue(
170      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
171  XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
172
173  // TextFormat
174  enumName = [descriptor textFormatNameForValue:1];
175  XCTAssertNotNil(enumName);
176  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:@"FOO"]);
177  XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
178  XCTAssertNil([descriptor textFormatNameForValue:99999]);
179
180  // Bad values
181  enumName = [descriptor enumNameForValue:0];
182  XCTAssertNil(enumName);
183  XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
184  XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
185  XCTAssertFalse([descriptor getValue:&value
186                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
187  XCTAssertFalse([descriptor getValue:NULL
188                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
189  XCTAssertFalse([descriptor getValue:NULL forEnumTextFormatName:@"Unknown"]);
190  XCTAssertFalse([descriptor getValue:&value forEnumTextFormatName:@"Unknown"]);
191}
192
193- (void)testEnumDescriptorIntrospection {
194  GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
195
196  XCTAssertEqual(descriptor.enumNameCount, 4U);
197  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0],
198                        @"TestAllTypes_NestedEnum_Foo");
199  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO");
200  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1],
201                 @"TestAllTypes_NestedEnum_Bar");
202  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR");
203  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2],
204                 @"TestAllTypes_NestedEnum_Baz");
205  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
206  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3],
207                 @"TestAllTypes_NestedEnum_Neg");
208  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"NEG");
209}
210
211- (void)testEnumDescriptorIntrospectionWithAlias {
212  GPBEnumDescriptor *descriptor = TestEnumWithDupValue_EnumDescriptor();
213  NSString *enumName;
214  int32_t value;
215
216  XCTAssertEqual(descriptor.enumNameCount, 5U);
217
218  enumName = [descriptor getEnumNameForIndex:0];
219  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo1");
220  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
221  XCTAssertEqual(value, 1);
222  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO1");
223
224  enumName = [descriptor getEnumNameForIndex:1];
225  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar1");
226  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
227  XCTAssertEqual(value, 2);
228  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR1");
229
230  enumName = [descriptor getEnumNameForIndex:2];
231  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Baz");
232  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
233  XCTAssertEqual(value, 3);
234  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
235
236  enumName = [descriptor getEnumNameForIndex:3];
237  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo2");
238  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
239  XCTAssertEqual(value, 1);
240  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"FOO2");
241
242  enumName = [descriptor getEnumNameForIndex:4];
243  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar2");
244  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
245  XCTAssertEqual(value, 2);
246  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:4], @"BAR2");
247}
248
249- (void)testEnumAliasNameCollisions {
250  GPBEnumDescriptor *descriptor = TestEnumObjCNameCollision_EnumDescriptor();
251  NSString *textFormatName;
252  int32_t value;
253
254  XCTAssertEqual(descriptor.enumNameCount, 5U);
255
256  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestEnumObjCNameCollision_Foo");
257  textFormatName = [descriptor getEnumTextFormatNameForIndex:0];
258  XCTAssertEqualObjects(textFormatName, @"FOO");
259  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
260  XCTAssertEqual(value, 1);
261
262  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestEnumObjCNameCollision_Foo");
263  textFormatName = [descriptor getEnumTextFormatNameForIndex:1];
264  XCTAssertEqualObjects(textFormatName, @"foo");
265  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
266  XCTAssertEqual(value, 1);
267
268  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestEnumObjCNameCollision_Bar");
269  textFormatName = [descriptor getEnumTextFormatNameForIndex:2];
270  XCTAssertEqualObjects(textFormatName, @"BAR");
271  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
272  XCTAssertEqual(value, 2);
273
274  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestEnumObjCNameCollision_Mumble");
275  textFormatName = [descriptor getEnumTextFormatNameForIndex:3];
276  XCTAssertEqualObjects(textFormatName, @"mumble");
277  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
278  XCTAssertEqual(value, 2);
279
280  XCTAssertEqualObjects([descriptor getEnumNameForIndex:4], @"TestEnumObjCNameCollision_Mumble");
281  textFormatName = [descriptor getEnumTextFormatNameForIndex:4];
282  XCTAssertEqualObjects(textFormatName, @"MUMBLE");
283  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
284  XCTAssertEqual(value, 2);
285}
286
287- (void)testEnumValueValidator {
288  GPBDescriptor *descriptor = [TestAllTypes descriptor];
289  GPBFieldDescriptor *fieldDescriptor =
290      [descriptor fieldWithName:@"optionalNestedEnum"];
291
292  // Valid values
293  XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
294  XCTAssertTrue([fieldDescriptor isValidEnumValue:2]);
295  XCTAssertTrue([fieldDescriptor isValidEnumValue:3]);
296  XCTAssertTrue([fieldDescriptor isValidEnumValue:-1]);
297
298  // Invalid values
299  XCTAssertFalse([fieldDescriptor isValidEnumValue:4]);
300  XCTAssertFalse([fieldDescriptor isValidEnumValue:0]);
301  XCTAssertFalse([fieldDescriptor isValidEnumValue:-2]);
302}
303
304- (void)testOneofDescriptor {
305  GPBDescriptor *descriptor = [TestOneof2 descriptor];
306
307  // All fields should be listed.
308  XCTAssertEqual(descriptor.fields.count, 17U);
309
310  // There are two oneofs in there.
311  XCTAssertEqual(descriptor.oneofs.count, 2U);
312
313  GPBFieldDescriptor *fooStringField =
314      [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
315  XCTAssertNotNil(fooStringField);
316  GPBFieldDescriptor *barStringField =
317      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
318  XCTAssertNotNil(barStringField);
319
320  // Check the oneofs to have what is expected.
321
322  GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
323  XCTAssertNotNil(oneofFoo);
324  XCTAssertEqual(oneofFoo.fields.count, 9U);
325
326  // Pointer comparisons.
327  XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
328                 fooStringField);
329  XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
330
331  GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
332  XCTAssertNotNil(oneofBar);
333  XCTAssertEqual(oneofBar.fields.count, 6U);
334
335  // Pointer comparisons.
336  XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
337                 barStringField);
338  XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
339
340  // Unknown oneof not found.
341
342  XCTAssertNil([descriptor oneofWithName:@"mumble"]);
343  XCTAssertNil([descriptor oneofWithName:@"Foo"]);
344
345  // Unknown oneof item.
346
347  XCTAssertNil([oneofFoo fieldWithName:@"mumble"]);
348  XCTAssertNil([oneofFoo fieldWithNumber:666]);
349
350  // Field exists, but not in this oneof.
351
352  XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
353  XCTAssertNil([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_BarString]);
354  XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
355  XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]);
356
357  // Check pointers back to the enclosing oneofs.
358  // (pointer comparisions)
359  XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
360  XCTAssertEqual(barStringField.containingOneof, oneofBar);
361  GPBFieldDescriptor *bazString =
362      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
363  XCTAssertNotNil(bazString);
364  XCTAssertNil(bazString.containingOneof);
365}
366
367- (void)testExtensiondDescriptor {
368  Class msgClass = [TestAllExtensions class];
369  Class packedMsgClass = [TestPackedExtensions class];
370
371  // Int
372
373  GPBExtensionDescriptor *descriptor = [UnittestRoot optionalInt32Extension];
374  XCTAssertNotNil(descriptor);
375  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
376  XCTAssertFalse(descriptor.isPackable);
377  XCTAssertEqualObjects(descriptor.defaultValue, @0);
378  XCTAssertNil(descriptor.enumDescriptor);
379
380  descriptor = [UnittestRoot defaultInt32Extension];
381  XCTAssertNotNil(descriptor);
382  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
383  XCTAssertFalse(descriptor.isPackable);
384  XCTAssertEqualObjects(descriptor.defaultValue, @41);
385  XCTAssertNil(descriptor.enumDescriptor);
386
387  // Enum
388
389  descriptor = [UnittestRoot optionalNestedEnumExtension];
390  XCTAssertNotNil(descriptor);
391  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
392  XCTAssertFalse(descriptor.isPackable);
393  XCTAssertEqual(descriptor.defaultValue, @1);
394  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
395
396  descriptor = [UnittestRoot defaultNestedEnumExtension];
397  XCTAssertNotNil(descriptor);
398  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
399  XCTAssertFalse(descriptor.isPackable);
400  XCTAssertEqual(descriptor.defaultValue, @2);
401  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
402
403  // Message
404
405  descriptor = [UnittestRoot optionalNestedMessageExtension];
406  XCTAssertNotNil(descriptor);
407  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
408  XCTAssertFalse(descriptor.isPackable);
409  XCTAssertNil(descriptor.defaultValue);
410  XCTAssertNil(descriptor.enumDescriptor);
411
412  // Repeated Int
413
414  descriptor = [UnittestRoot repeatedInt32Extension];
415  XCTAssertNotNil(descriptor);
416  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
417  XCTAssertFalse(descriptor.isPackable);
418  XCTAssertNil(descriptor.defaultValue);
419  XCTAssertNil(descriptor.enumDescriptor);
420
421  descriptor = [UnittestRoot packedInt32Extension];
422  XCTAssertNotNil(descriptor);
423  XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass);  // ptr equality
424  XCTAssertTrue(descriptor.isPackable);
425  XCTAssertNil(descriptor.defaultValue);
426  XCTAssertNil(descriptor.enumDescriptor);
427
428  // Repeated Enum
429
430  descriptor = [UnittestRoot repeatedNestedEnumExtension];
431  XCTAssertNotNil(descriptor);
432  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
433  XCTAssertFalse(descriptor.isPackable);
434  XCTAssertNil(descriptor.defaultValue);
435  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
436
437  descriptor = [UnittestRoot packedEnumExtension];
438  XCTAssertNotNil(descriptor);
439  XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass);  // ptr equality
440  XCTAssertTrue(descriptor.isPackable);
441  XCTAssertNil(descriptor.defaultValue);
442  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"ForeignEnum");
443
444  // Repeated Message
445
446  descriptor = [UnittestRoot repeatedNestedMessageExtension];
447  XCTAssertNotNil(descriptor);
448  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
449  XCTAssertFalse(descriptor.isPackable);
450  XCTAssertNil(descriptor.defaultValue);
451  XCTAssertNil(descriptor.enumDescriptor);
452
453  // Compare (used internally for serialization).
454
455  GPBExtensionDescriptor *ext1 = [UnittestRoot optionalInt32Extension];
456  XCTAssertEqual(ext1.fieldNumber, 1u);
457  GPBExtensionDescriptor *ext2 = [UnittestRoot optionalInt64Extension];
458  XCTAssertEqual(ext2.fieldNumber, 2u);
459
460  XCTAssertEqual([ext1 compareByFieldNumber:ext2], NSOrderedAscending);
461  XCTAssertEqual([ext2 compareByFieldNumber:ext1], NSOrderedDescending);
462  XCTAssertEqual([ext1 compareByFieldNumber:ext1], NSOrderedSame);
463}
464
465@end
466