• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Protocol Buffers - Google's data interchange format
2// Copyright 2008 Google Inc.  All rights reserved.
3//
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file or at
6// https://developers.google.com/open-source/licenses/bsd
7
8#import <objc/runtime.h>
9
10#import "GPBDescriptor.h"
11#import "GPBDescriptor_PackagePrivate.h"
12#import "GPBTestUtilities.h"
13#import "objectivec/Tests/Unittest.pbobjc.h"
14#import "objectivec/Tests/UnittestObjc.pbobjc.h"
15#import "objectivec/Tests/UnittestObjcOptions.pbobjc.h"
16
17@interface DescriptorTests : GPBTestCase
18@end
19
20@implementation DescriptorTests
21
22- (void)testDescriptor_containingType {
23  GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
24  GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
25  XCTAssertNil(testAllTypesDesc.containingType);
26  XCTAssertNotNil(nestedMessageDesc.containingType);
27  XCTAssertEqual(nestedMessageDesc.containingType, testAllTypesDesc);  // Ptr comparison
28}
29
30- (void)testDescriptor_fullName {
31  GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
32  XCTAssertEqualObjects(testAllTypesDesc.fullName, @"objc.protobuf.tests.TestAllTypes");
33  GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
34  XCTAssertEqualObjects(nestedMessageDesc.fullName,
35                        @"objc.protobuf.tests.TestAllTypes.NestedMessage");
36
37  // Prefixes removed.
38  GPBDescriptor *descDesc = [GPBTESTPrefixedParentMessage descriptor];
39  XCTAssertEqualObjects(descDesc.fullName, @"objc.protobuf.tests.options.PrefixedParentMessage");
40  GPBDescriptor *descExtRngDesc = [GPBTESTPrefixedParentMessage_Child descriptor];
41  XCTAssertEqualObjects(descExtRngDesc.fullName,
42                        @"objc.protobuf.tests.options.PrefixedParentMessage.Child");
43
44  // Things that get "_Class" added.
45  GPBDescriptor *pointDesc = [Point_Class descriptor];
46  XCTAssertEqualObjects(pointDesc.fullName, @"objc.protobuf.tests.Point");
47  GPBDescriptor *pointRectDesc = [Point_Rect descriptor];
48  XCTAssertEqualObjects(pointRectDesc.fullName, @"objc.protobuf.tests.Point.Rect");
49}
50
51- (void)testFieldDescriptor {
52  GPBDescriptor *descriptor = [TestAllTypes descriptor];
53
54  // Nested Enum
55  GPBFieldDescriptor *fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedEnum"];
56  XCTAssertNotNil(fieldDescriptorWithName);
57  GPBFieldDescriptor *fieldDescriptorWithNumber = [descriptor fieldWithNumber:21];
58  XCTAssertNotNil(fieldDescriptorWithNumber);
59  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
60  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
61  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"TestAllTypes_NestedEnum");
62  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
63  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
64
65  // Foreign Enum
66  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"];
67  XCTAssertNotNil(fieldDescriptorWithName);
68  fieldDescriptorWithNumber = [descriptor fieldWithNumber:22];
69  XCTAssertNotNil(fieldDescriptorWithNumber);
70  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
71  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
72  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ForeignEnum");
73  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
74  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
75
76  // Import Enum
77  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"];
78  XCTAssertNotNil(fieldDescriptorWithName);
79  fieldDescriptorWithNumber = [descriptor fieldWithNumber:23];
80  XCTAssertNotNil(fieldDescriptorWithNumber);
81  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
82  XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
83  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ImportEnum");
84  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
85  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
86
87  // Nested Message
88  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"];
89  XCTAssertNotNil(fieldDescriptorWithName);
90  fieldDescriptorWithNumber = [descriptor fieldWithNumber:18];
91  XCTAssertNotNil(fieldDescriptorWithNumber);
92  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
93  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
94  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
95  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
96
97  // Foreign Message
98  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignMessage"];
99  XCTAssertNotNil(fieldDescriptorWithName);
100  fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
101  XCTAssertNotNil(fieldDescriptorWithNumber);
102  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
103  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
104  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
105  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
106
107  // Import Message
108  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"];
109  XCTAssertNotNil(fieldDescriptorWithName);
110  fieldDescriptorWithNumber = [descriptor fieldWithNumber:20];
111  XCTAssertNotNil(fieldDescriptorWithNumber);
112  XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
113  XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
114  XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
115  XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
116
117  // Some failed lookups.
118  XCTAssertNil([descriptor fieldWithName:@"NOT THERE"]);
119  XCTAssertNil([descriptor fieldWithNumber:9876543]);
120}
121
122- (void)testEnumDescriptor {
123  GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
124
125  NSString *enumName = [descriptor enumNameForValue:1];
126  XCTAssertNotNil(enumName);
127  int32_t value;
128  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
129  XCTAssertTrue([descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
130  XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
131
132  enumName = [descriptor enumNameForValue:2];
133  XCTAssertNotNil(enumName);
134  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
135  XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
136
137  enumName = [descriptor enumNameForValue:3];
138  XCTAssertNotNil(enumName);
139  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
140  XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
141
142  // TextFormat
143  enumName = [descriptor textFormatNameForValue:1];
144  XCTAssertNotNil(enumName);
145  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:@"FOO"]);
146  XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
147  XCTAssertNil([descriptor textFormatNameForValue:99999]);
148
149  // Bad values
150  enumName = [descriptor enumNameForValue:0];
151  XCTAssertNil(enumName);
152  XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
153  XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
154  XCTAssertFalse([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
155  XCTAssertFalse([descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
156  XCTAssertFalse([descriptor getValue:NULL forEnumTextFormatName:@"Unknown"]);
157  XCTAssertFalse([descriptor getValue:&value forEnumTextFormatName:@"Unknown"]);
158}
159
160- (void)testEnumDescriptorIntrospection {
161  GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
162
163  XCTAssertEqual(descriptor.enumNameCount, 4U);
164  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestAllTypes_NestedEnum_Foo");
165  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO");
166  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestAllTypes_NestedEnum_Bar");
167  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR");
168  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestAllTypes_NestedEnum_Baz");
169  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
170  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestAllTypes_NestedEnum_Neg");
171  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"NEG");
172}
173
174- (void)testEnumDescriptorIntrospectionWithAlias {
175  GPBEnumDescriptor *descriptor = TestEnumWithDupValue_EnumDescriptor();
176  NSString *enumName;
177  int32_t value;
178
179  XCTAssertEqual(descriptor.enumNameCount, 5U);
180
181  enumName = [descriptor getEnumNameForIndex:0];
182  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo1");
183  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
184  XCTAssertEqual(value, 1);
185  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO1");
186
187  enumName = [descriptor getEnumNameForIndex:1];
188  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar1");
189  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
190  XCTAssertEqual(value, 2);
191  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR1");
192
193  enumName = [descriptor getEnumNameForIndex:2];
194  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Baz");
195  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
196  XCTAssertEqual(value, 3);
197  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
198
199  enumName = [descriptor getEnumNameForIndex:3];
200  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Foo2");
201  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
202  XCTAssertEqual(value, 1);
203  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"FOO2");
204
205  enumName = [descriptor getEnumNameForIndex:4];
206  XCTAssertEqualObjects(enumName, @"TestEnumWithDupValue_Bar2");
207  XCTAssertTrue([descriptor getValue:&value forEnumName:enumName]);
208  XCTAssertEqual(value, 2);
209  XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:4], @"BAR2");
210}
211
212- (void)testEnumAliasNameCollisions {
213  GPBEnumDescriptor *descriptor = TestEnumObjCNameCollision_EnumDescriptor();
214  NSString *textFormatName;
215  int32_t value;
216
217  XCTAssertEqual(descriptor.enumNameCount, 5U);
218
219  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestEnumObjCNameCollision_Foo");
220  textFormatName = [descriptor getEnumTextFormatNameForIndex:0];
221  XCTAssertEqualObjects(textFormatName, @"FOO");
222  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
223  XCTAssertEqual(value, 1);
224
225  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestEnumObjCNameCollision_Foo");
226  textFormatName = [descriptor getEnumTextFormatNameForIndex:1];
227  XCTAssertEqualObjects(textFormatName, @"foo");
228  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
229  XCTAssertEqual(value, 1);
230
231  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestEnumObjCNameCollision_Bar");
232  textFormatName = [descriptor getEnumTextFormatNameForIndex:2];
233  XCTAssertEqualObjects(textFormatName, @"BAR");
234  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
235  XCTAssertEqual(value, 2);
236
237  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestEnumObjCNameCollision_Mumble");
238  textFormatName = [descriptor getEnumTextFormatNameForIndex:3];
239  XCTAssertEqualObjects(textFormatName, @"mumble");
240  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
241  XCTAssertEqual(value, 2);
242
243  XCTAssertEqualObjects([descriptor getEnumNameForIndex:4], @"TestEnumObjCNameCollision_Mumble");
244  textFormatName = [descriptor getEnumTextFormatNameForIndex:4];
245  XCTAssertEqualObjects(textFormatName, @"MUMBLE");
246  XCTAssertTrue([descriptor getValue:&value forEnumTextFormatName:textFormatName]);
247  XCTAssertEqual(value, 2);
248}
249
250- (void)testEnumValueValidator {
251  GPBDescriptor *descriptor = [TestAllTypes descriptor];
252  GPBFieldDescriptor *fieldDescriptor = [descriptor fieldWithName:@"optionalNestedEnum"];
253
254  // Valid values
255  XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
256  XCTAssertTrue([fieldDescriptor isValidEnumValue:2]);
257  XCTAssertTrue([fieldDescriptor isValidEnumValue:3]);
258  XCTAssertTrue([fieldDescriptor isValidEnumValue:-1]);
259
260  // Invalid values
261  XCTAssertFalse([fieldDescriptor isValidEnumValue:4]);
262  XCTAssertFalse([fieldDescriptor isValidEnumValue:0]);
263  XCTAssertFalse([fieldDescriptor isValidEnumValue:-2]);
264}
265
266- (void)testOneofDescriptor {
267  GPBDescriptor *descriptor = [TestOneof2 descriptor];
268
269  GPBFieldDescriptor *fooStringField =
270      [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
271  XCTAssertNotNil(fooStringField);
272  GPBFieldDescriptor *barStringField =
273      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
274  XCTAssertNotNil(barStringField);
275
276  // Check the oneofs to have what is expected but not other onesofs
277
278  GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
279  XCTAssertNotNil(oneofFoo);
280  XCTAssertNotNil([oneofFoo fieldWithName:@"fooString"]);
281  XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
282
283  GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
284  XCTAssertNotNil(oneofBar);
285  XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
286  XCTAssertNotNil([oneofBar fieldWithName:@"barString"]);
287
288  // Pointer comparisons against lookups from message.
289
290  XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString], fooStringField);
291  XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
292
293  XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString], barStringField);
294  XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
295
296  // Unknown oneof not found.
297
298  XCTAssertNil([descriptor oneofWithName:@"mumble"]);
299  XCTAssertNil([descriptor oneofWithName:@"Foo"]);
300
301  // Unknown oneof item.
302
303  XCTAssertNil([oneofFoo fieldWithName:@"mumble"]);
304  XCTAssertNil([oneofFoo fieldWithNumber:666]);
305
306  // Field exists, but not in this oneof.
307
308  XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
309  XCTAssertNil([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_BarString]);
310  XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
311  XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]);
312
313  // Check pointers back to the enclosing oneofs.
314  // (pointer comparisons)
315  XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
316  XCTAssertEqual(barStringField.containingOneof, oneofBar);
317  GPBFieldDescriptor *bazString = [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
318  XCTAssertNotNil(bazString);
319  XCTAssertNil(bazString.containingOneof);
320}
321
322- (void)testExtensiondDescriptor {
323  Class msgClass = [TestAllExtensions class];
324  Class packedMsgClass = [TestPackedExtensions class];
325
326  // Int
327
328  GPBExtensionDescriptor *descriptor = [UnittestRoot optionalInt32Extension];
329  XCTAssertNotNil(descriptor);
330  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
331  XCTAssertFalse(descriptor.isPackable);
332  XCTAssertEqualObjects(descriptor.defaultValue, @0);
333  XCTAssertNil(descriptor.enumDescriptor);
334
335  descriptor = [UnittestRoot defaultInt32Extension];
336  XCTAssertNotNil(descriptor);
337  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
338  XCTAssertFalse(descriptor.isPackable);
339  XCTAssertEqualObjects(descriptor.defaultValue, @41);
340  XCTAssertNil(descriptor.enumDescriptor);
341
342  // Enum
343
344  descriptor = [UnittestRoot optionalNestedEnumExtension];
345  XCTAssertNotNil(descriptor);
346  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
347  XCTAssertFalse(descriptor.isPackable);
348  XCTAssertEqual(descriptor.defaultValue, @1);
349  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
350
351  descriptor = [UnittestRoot defaultNestedEnumExtension];
352  XCTAssertNotNil(descriptor);
353  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
354  XCTAssertFalse(descriptor.isPackable);
355  XCTAssertEqual(descriptor.defaultValue, @2);
356  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
357
358  // Message
359
360  descriptor = [UnittestRoot optionalNestedMessageExtension];
361  XCTAssertNotNil(descriptor);
362  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
363  XCTAssertFalse(descriptor.isPackable);
364  XCTAssertNil(descriptor.defaultValue);
365  XCTAssertNil(descriptor.enumDescriptor);
366
367  // Repeated Int
368
369  descriptor = [UnittestRoot repeatedInt32Extension];
370  XCTAssertNotNil(descriptor);
371  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
372  XCTAssertFalse(descriptor.isPackable);
373  XCTAssertNil(descriptor.defaultValue);
374  XCTAssertNil(descriptor.enumDescriptor);
375
376  descriptor = [UnittestRoot packedInt32Extension];
377  XCTAssertNotNil(descriptor);
378  XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass);  // ptr equality
379  XCTAssertTrue(descriptor.isPackable);
380  XCTAssertNil(descriptor.defaultValue);
381  XCTAssertNil(descriptor.enumDescriptor);
382
383  // Repeated Enum
384
385  descriptor = [UnittestRoot repeatedNestedEnumExtension];
386  XCTAssertNotNil(descriptor);
387  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
388  XCTAssertFalse(descriptor.isPackable);
389  XCTAssertNil(descriptor.defaultValue);
390  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"TestAllTypes_NestedEnum");
391
392  descriptor = [UnittestRoot packedEnumExtension];
393  XCTAssertNotNil(descriptor);
394  XCTAssertEqual(descriptor.containingMessageClass, packedMsgClass);  // ptr equality
395  XCTAssertTrue(descriptor.isPackable);
396  XCTAssertNil(descriptor.defaultValue);
397  XCTAssertEqualObjects(descriptor.enumDescriptor.name, @"ForeignEnum");
398
399  // Repeated Message
400
401  descriptor = [UnittestRoot repeatedNestedMessageExtension];
402  XCTAssertNotNil(descriptor);
403  XCTAssertEqual(descriptor.containingMessageClass, msgClass);  // ptr equality
404  XCTAssertFalse(descriptor.isPackable);
405  XCTAssertNil(descriptor.defaultValue);
406  XCTAssertNil(descriptor.enumDescriptor);
407
408  // Compare (used internally for serialization).
409
410  GPBExtensionDescriptor *ext1 = [UnittestRoot optionalInt32Extension];
411  XCTAssertEqual(ext1.fieldNumber, 1u);
412  GPBExtensionDescriptor *ext2 = [UnittestRoot optionalInt64Extension];
413  XCTAssertEqual(ext2.fieldNumber, 2u);
414
415  XCTAssertEqual([ext1 compareByFieldNumber:ext2], NSOrderedAscending);
416  XCTAssertEqual([ext2 compareByFieldNumber:ext1], NSOrderedDescending);
417  XCTAssertEqual([ext1 compareByFieldNumber:ext1], NSOrderedSame);
418}
419
420@end
421