blob: 8a8ba93e5c36c99dcdce3725fdbd14fbca11df01 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001// 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 <XCTest/XCTest.h>
32
33#import "GPBUtilities_PackagePrivate.h"
34
35#import <objc/runtime.h>
36
37#import "GPBTestUtilities.h"
38
39#import "GPBDescriptor.h"
40#import "GPBDescriptor_PackagePrivate.h"
41#import "GPBMessage.h"
Austin Schuh40c16522018-10-28 20:27:54 -070042#import "GPBUnknownField_PackagePrivate.h"
Brian Silverman9c614bc2016-02-15 20:20:02 -050043
44#import "google/protobuf/MapUnittest.pbobjc.h"
45#import "google/protobuf/Unittest.pbobjc.h"
46#import "google/protobuf/UnittestObjc.pbobjc.h"
47
48@interface UtilitiesTests : GPBTestCase
49@end
50
51@implementation UtilitiesTests
52
53- (void)testRightShiftFunctions {
54 XCTAssertEqual((1UL << 31) >> 31, 1UL);
Austin Schuh40c16522018-10-28 20:27:54 -070055 XCTAssertEqual((int32_t)(1U << 31) >> 31, -1);
Brian Silverman9c614bc2016-02-15 20:20:02 -050056 XCTAssertEqual((1ULL << 63) >> 63, 1ULL);
Austin Schuh40c16522018-10-28 20:27:54 -070057 XCTAssertEqual((int64_t)(1ULL << 63) >> 63, -1LL);
Brian Silverman9c614bc2016-02-15 20:20:02 -050058
Austin Schuh40c16522018-10-28 20:27:54 -070059 XCTAssertEqual(GPBLogicalRightShift32((1U << 31), 31), 1);
60 XCTAssertEqual(GPBLogicalRightShift64((1ULL << 63), 63), 1LL);
Brian Silverman9c614bc2016-02-15 20:20:02 -050061}
62
63- (void)testGPBDecodeTextFormatName {
64 uint8_t decodeData[] = {
65 0x6,
66 // An inlined string (first to make sure the leading null is handled
67 // correctly, and with a key of zero to check that).
68 0x0, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
69 // All as is (00 op)
70 0x1, 0x0A, 0x0,
71 // Underscore, upper + 9 (10 op)
72 0x3, 0xCA, 0x0,
73 // Upper + 3 (10 op), underscore, upper + 5 (10 op)
74 0x2, 0x44, 0xC6, 0x0,
75 // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
76 // underscore, lower + 0 (01 op)
77 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
78 // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
79 // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
80 // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op),
81 // underscore, as is + 3 (00 op)
82 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
83 };
84 NSString *inputStr = @"abcdefghIJ";
85
86 // Empty inputs
87
88 XCTAssertNil(GPBDecodeTextFormatName(nil, 1, NULL));
89 XCTAssertNil(GPBDecodeTextFormatName(decodeData, 1, NULL));
90 XCTAssertNil(GPBDecodeTextFormatName(nil, 1, inputStr));
91
92 // Keys not found.
93
94 XCTAssertNil(GPBDecodeTextFormatName(decodeData, 5, inputStr));
95 XCTAssertNil(GPBDecodeTextFormatName(decodeData, -1, inputStr));
96
97 // Some name decodes.
98
99 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1, inputStr), @"abcdefghIJ");
100 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 2, inputStr), @"Abcd_EfghIJ");
101 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 3, inputStr), @"_AbcdefghIJ");
102 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 4, inputStr), @"ABCD__EfghI_j");
103
104 // An inlined string (and key of zero).
105 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ");
106
107 // Long name so multiple decode ops are needed.
108 inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
109 XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr),
110 @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
111}
112
113- (void)testTextFormat {
114 TestAllTypes *message = [TestAllTypes message];
115
116 // Not kGPBDefaultRepeatCount because we are comparing to golden master file
117 // which was generated with 2.
118 [self setAllFields:message repeatedCount:2];
119
120 NSString *result = GPBTextFormatForMessage(message, nil);
121
122 NSString *fileName = @"text_format_unittest_data.txt";
123 NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
124 NSData *expectedData =
125 [self getDataFileNamed:fileName dataToWrite:resultData];
126 NSString *expected = [[NSString alloc] initWithData:expectedData
127 encoding:NSUTF8StringEncoding];
128 XCTAssertEqualObjects(expected, result);
129 [expected release];
130}
131
132- (void)testTextFormatExtra {
133 // -testTextFormat uses all protos with fields that don't require special
134 // handing for figuring out the names. The ObjC proto has a bunch of oddball
135 // field and enum names that require the decode info to get right, so this
136 // confirms they generated and decoded correctly.
137
138 self_Class *message = [self_Class message];
139 message.cmd = YES;
140 message.isProxy_p = YES;
141 message.subEnum = self_autorelease_RetainCount;
142 message.new_p.copy_p = @"foo";
143
144 NSString *expected = @"_cmd: true\n"
145 @"isProxy: true\n"
146 @"SubEnum: retainCount\n"
147 @"New {\n"
148 @" copy: \"foo\"\n"
149 @"}\n";
150 NSString *result = GPBTextFormatForMessage(message, nil);
151 XCTAssertEqualObjects(expected, result);
152}
153
154- (void)testTextFormatMaps {
155 TestMap *message = [TestMap message];
156
157 // Map iteration order doesn't have to be stable, so use only one entry.
158 [self setAllMapFields:message numEntries:1];
159
160 NSString *result = GPBTextFormatForMessage(message, nil);
161
162 NSString *fileName = @"text_format_map_unittest_data.txt";
163 NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
164 NSData *expectedData =
165 [self getDataFileNamed:fileName dataToWrite:resultData];
166 NSString *expected = [[NSString alloc] initWithData:expectedData
167 encoding:NSUTF8StringEncoding];
168 XCTAssertEqualObjects(expected, result);
169 [expected release];
170}
171
172// TODO(thomasvl): add test with extensions once those format with correct names.
173
Austin Schuh40c16522018-10-28 20:27:54 -0700174- (void)testSetRepeatedFields {
175 TestAllTypes *message = [TestAllTypes message];
176
177 NSDictionary *repeatedFieldValues = @{
178 @"repeatedStringArray" : [@[@"foo", @"bar"] mutableCopy],
179 @"repeatedBoolArray" : [GPBBoolArray arrayWithValue:YES],
180 @"repeatedInt32Array" : [GPBInt32Array arrayWithValue:14],
181 @"repeatedInt64Array" : [GPBInt64Array arrayWithValue:15],
182 @"repeatedUint32Array" : [GPBUInt32Array arrayWithValue:16],
183 @"repeatedUint64Array" : [GPBUInt64Array arrayWithValue:16],
184 @"repeatedFloatArray" : [GPBFloatArray arrayWithValue:16],
185 @"repeatedDoubleArray" : [GPBDoubleArray arrayWithValue:16],
186 @"repeatedNestedEnumArray" :
187 [GPBEnumArray arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue
188 rawValue:TestAllTypes_NestedEnum_Foo],
189 };
190 for (NSString *fieldName in repeatedFieldValues) {
191 GPBFieldDescriptor *field =
192 [message.descriptor fieldWithName:fieldName];
193 XCTAssertNotNil(field, @"No field with name: %@", fieldName);
194 id expectedValues = repeatedFieldValues[fieldName];
195 GPBSetMessageRepeatedField(message, field, expectedValues);
196 XCTAssertEqualObjects(expectedValues,
197 [message valueForKeyPath:fieldName]);
198 }
199}
200
201// Helper to make an unknown field set with something in it.
202static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
203 GPBUnknownFieldSet *result =
204 [[[GPBUnknownFieldSet alloc] init] autorelease];
205
206 GPBUnknownField *field =
207 [[[GPBUnknownField alloc] initWithNumber:num] autorelease];
208 [field addVarint:num];
209 [result addField:field];
210
211 return result;
212}
213
214- (void)testDropMessageUnknownFieldsRecursively {
215 TestAllExtensions *message = [TestAllExtensions message];
216
217 // Give it unknownFields.
218 message.unknownFields = UnknownFieldsSetHelper(777);
219
220 // Given it extensions that include a message with unknown fields of its own.
221 {
222 // Int
223 [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
224
225 // Group
226 OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
227 optionalGroup.a = 123;
228 optionalGroup.unknownFields = UnknownFieldsSetHelper(779);
229 [message setExtension:[UnittestRoot optionalGroupExtension]
230 value:optionalGroup];
231
232 // Message
233 TestAllTypes_NestedMessage *nestedMessage =
234 [TestAllTypes_NestedMessage message];
235 nestedMessage.bb = 456;
236 nestedMessage.unknownFields = UnknownFieldsSetHelper(778);
237 [message setExtension:[UnittestRoot optionalNestedMessageExtension]
238 value:nestedMessage];
239
240 // Repeated Group
241 RepeatedGroup_extension *repeatedGroup =
242 [[RepeatedGroup_extension alloc] init];
243 repeatedGroup.a = 567;
244 repeatedGroup.unknownFields = UnknownFieldsSetHelper(780);
245 [message addExtension:[UnittestRoot repeatedGroupExtension]
246 value:repeatedGroup];
247 [repeatedGroup release];
248
249 // Repeated Message
250 nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
251 nestedMessage.bb = 678;
252 nestedMessage.unknownFields = UnknownFieldsSetHelper(781);
253 [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
254 value:nestedMessage];
255 [nestedMessage release];
256 }
257
258 // Confirm everything is there.
259
260 XCTAssertNotNil(message);
261 XCTAssertNotNil(message.unknownFields);
262 XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
263
264 {
265 XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]);
266 OptionalGroup_extension *optionalGroup =
267 [message getExtension:[UnittestRoot optionalGroupExtension]];
268 XCTAssertNotNil(optionalGroup);
269 XCTAssertEqual(optionalGroup.a, 123);
270 XCTAssertNotNil(optionalGroup.unknownFields);
271 }
272
273 {
274 XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
275 TestAllTypes_NestedMessage *nestedMessage =
276 [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
277 XCTAssertNotNil(nestedMessage);
278 XCTAssertEqual(nestedMessage.bb, 456);
279 XCTAssertNotNil(nestedMessage.unknownFields);
280 }
281
282 {
283 XCTAssertTrue([message hasExtension:[UnittestRoot repeatedGroupExtension]]);
284 NSArray *repeatedGroups = [message getExtension:[UnittestRoot repeatedGroupExtension]];
285 XCTAssertEqual(repeatedGroups.count, (NSUInteger)1);
286 RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
287 XCTAssertNotNil(repeatedGroup);
288 XCTAssertEqual(repeatedGroup.a, 567);
289 XCTAssertNotNil(repeatedGroup.unknownFields);
290 }
291
292 {
293 XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]);
294 NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
295 XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1);
296 TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
297 XCTAssertNotNil(repeatedNestedMessage);
298 XCTAssertEqual(repeatedNestedMessage.bb, 678);
299 XCTAssertNotNil(repeatedNestedMessage.unknownFields);
300 }
301
302 // Drop them.
303 GPBMessageDropUnknownFieldsRecursively(message);
304
305 // Confirm unknowns are gone from within the messages.
306
307 XCTAssertNotNil(message);
308 XCTAssertNil(message.unknownFields);
309 XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
310
311 {
312 XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]);
313 OptionalGroup_extension *optionalGroup =
314 [message getExtension:[UnittestRoot optionalGroupExtension]];
315 XCTAssertNotNil(optionalGroup);
316 XCTAssertEqual(optionalGroup.a, 123);
317 XCTAssertNil(optionalGroup.unknownFields);
318 }
319
320 {
321 XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
322 TestAllTypes_NestedMessage *nestedMessage =
323 [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
324 XCTAssertNotNil(nestedMessage);
325 XCTAssertEqual(nestedMessage.bb, 456);
326 XCTAssertNil(nestedMessage.unknownFields);
327 }
328
329 {
330 XCTAssertTrue([message hasExtension:[UnittestRoot repeatedGroupExtension]]);
331 NSArray *repeatedGroups = [message getExtension:[UnittestRoot repeatedGroupExtension]];
332 XCTAssertEqual(repeatedGroups.count, (NSUInteger)1);
333 RepeatedGroup_extension *repeatedGroup = repeatedGroups.firstObject;
334 XCTAssertNotNil(repeatedGroup);
335 XCTAssertEqual(repeatedGroup.a, 567);
336 XCTAssertNil(repeatedGroup.unknownFields);
337 }
338
339 {
340 XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]);
341 NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
342 XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1);
343 TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
344 XCTAssertNotNil(repeatedNestedMessage);
345 XCTAssertEqual(repeatedNestedMessage.bb, 678);
346 XCTAssertNil(repeatedNestedMessage.unknownFields);
347 }
348
349}
350
351- (void)testDropMessageUnknownFieldsRecursively_Maps {
352 TestMap *message = [TestMap message];
353
354 {
355 ForeignMessage *foreignMessage = [ForeignMessage message];
356 foreignMessage.unknownFields = UnknownFieldsSetHelper(100);
357 [message.mapInt32ForeignMessage setObject:foreignMessage forKey:100];
358
359 foreignMessage = [ForeignMessage message];
360 foreignMessage.unknownFields = UnknownFieldsSetHelper(101);
361 [message.mapStringForeignMessage setObject:foreignMessage forKey:@"101"];
362 }
363
364 // Confirm everything is there.
365
366 XCTAssertNotNil(message);
367
368 {
369 ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
370 XCTAssertNotNil(foreignMessage);
371 XCTAssertNotNil(foreignMessage.unknownFields);
372 }
373
374 {
375 ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
376 XCTAssertNotNil(foreignMessage);
377 XCTAssertNotNil(foreignMessage.unknownFields);
378 }
379
380 GPBMessageDropUnknownFieldsRecursively(message);
381
382 // Confirm unknowns are gone from within the messages.
383
384 XCTAssertNotNil(message);
385
386 {
387 ForeignMessage *foreignMessage = [message.mapInt32ForeignMessage objectForKey:100];
388 XCTAssertNotNil(foreignMessage);
389 XCTAssertNil(foreignMessage.unknownFields);
390 }
391
392 {
393 ForeignMessage *foreignMessage = [message.mapStringForeignMessage objectForKey:@"101"];
394 XCTAssertNotNil(foreignMessage);
395 XCTAssertNil(foreignMessage.unknownFields);
396 }
397
398}
399
Brian Silverman9c614bc2016-02-15 20:20:02 -0500400@end