xref: /aosp_15_r20/external/protobuf/objectivec/Tests/GPBCodedInputStreamTests.m (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format
2*1b3f573fSAndroid Build Coastguard Worker// Copyright 2008 Google Inc.  All rights reserved.
3*1b3f573fSAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/
4*1b3f573fSAndroid Build Coastguard Worker//
5*1b3f573fSAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without
6*1b3f573fSAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are
7*1b3f573fSAndroid Build Coastguard Worker// met:
8*1b3f573fSAndroid Build Coastguard Worker//
9*1b3f573fSAndroid Build Coastguard Worker//     * Redistributions of source code must retain the above copyright
10*1b3f573fSAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer.
11*1b3f573fSAndroid Build Coastguard Worker//     * Redistributions in binary form must reproduce the above
12*1b3f573fSAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer
13*1b3f573fSAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the
14*1b3f573fSAndroid Build Coastguard Worker// distribution.
15*1b3f573fSAndroid Build Coastguard Worker//     * Neither the name of Google Inc. nor the names of its
16*1b3f573fSAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from
17*1b3f573fSAndroid Build Coastguard Worker// this software without specific prior written permission.
18*1b3f573fSAndroid Build Coastguard Worker//
19*1b3f573fSAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*1b3f573fSAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*1b3f573fSAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23*1b3f573fSAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24*1b3f573fSAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26*1b3f573fSAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27*1b3f573fSAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28*1b3f573fSAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29*1b3f573fSAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*1b3f573fSAndroid Build Coastguard Worker
31*1b3f573fSAndroid Build Coastguard Worker#import "GPBTestUtilities.h"
32*1b3f573fSAndroid Build Coastguard Worker
33*1b3f573fSAndroid Build Coastguard Worker#import "GPBCodedInputStream.h"
34*1b3f573fSAndroid Build Coastguard Worker#import "GPBCodedOutputStream.h"
35*1b3f573fSAndroid Build Coastguard Worker#import "GPBUnknownFieldSet_PackagePrivate.h"
36*1b3f573fSAndroid Build Coastguard Worker#import "GPBUtilities_PackagePrivate.h"
37*1b3f573fSAndroid Build Coastguard Worker#import "google/protobuf/Unittest.pbobjc.h"
38*1b3f573fSAndroid Build Coastguard Worker
39*1b3f573fSAndroid Build Coastguard Worker@interface CodedInputStreamTests : GPBTestCase
40*1b3f573fSAndroid Build Coastguard Worker@end
41*1b3f573fSAndroid Build Coastguard Worker
42*1b3f573fSAndroid Build Coastguard Worker@implementation CodedInputStreamTests
43*1b3f573fSAndroid Build Coastguard Worker
44*1b3f573fSAndroid Build Coastguard Worker- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
45*1b3f573fSAndroid Build Coastguard Worker  va_list list;
46*1b3f573fSAndroid Build Coastguard Worker  va_start(list, unused);
47*1b3f573fSAndroid Build Coastguard Worker
48*1b3f573fSAndroid Build Coastguard Worker  NSMutableData* values = [NSMutableData dataWithCapacity:0];
49*1b3f573fSAndroid Build Coastguard Worker  int32_t i;
50*1b3f573fSAndroid Build Coastguard Worker
51*1b3f573fSAndroid Build Coastguard Worker  while ((i = va_arg(list, int32_t)) != 256) {
52*1b3f573fSAndroid Build Coastguard Worker    NSAssert(i >= 0 && i < 256, @"");
53*1b3f573fSAndroid Build Coastguard Worker    uint8_t u = (uint8_t)i;
54*1b3f573fSAndroid Build Coastguard Worker    [values appendBytes:&u length:1];
55*1b3f573fSAndroid Build Coastguard Worker  }
56*1b3f573fSAndroid Build Coastguard Worker
57*1b3f573fSAndroid Build Coastguard Worker  va_end(list);
58*1b3f573fSAndroid Build Coastguard Worker
59*1b3f573fSAndroid Build Coastguard Worker  return values;
60*1b3f573fSAndroid Build Coastguard Worker}
61*1b3f573fSAndroid Build Coastguard Worker
62*1b3f573fSAndroid Build Coastguard Worker#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
63*1b3f573fSAndroid Build Coastguard Worker
64*1b3f573fSAndroid Build Coastguard Worker- (void)testDecodeZigZag {
65*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0x0) value:0];
66*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0x1) value:-1];
67*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0x2) value:1];
68*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0x3) value:-2];
69*1b3f573fSAndroid Build Coastguard Worker
70*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF];
71*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000];
72*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF];
73*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag32:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000];
74*1b3f573fSAndroid Build Coastguard Worker
75*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0x0) value:0];
76*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0x1) value:-1];
77*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0x2) value:1];
78*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0x3) value:-2];
79*1b3f573fSAndroid Build Coastguard Worker
80*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0x3FFFFFFF];
81*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x07) value:(int32_t)0xC0000000];
82*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF];
83*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000];
84*1b3f573fSAndroid Build Coastguard Worker
85*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x7FFFFFFFFFFFFFFFL];
86*1b3f573fSAndroid Build Coastguard Worker  [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x8000000000000000L];
87*1b3f573fSAndroid Build Coastguard Worker}
88*1b3f573fSAndroid Build Coastguard Worker
89*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadVarint:(NSData*)data value:(int64_t)value {
90*1b3f573fSAndroid Build Coastguard Worker  if (value <= INT32_MAX && value >= INT32_MIN) {
91*1b3f573fSAndroid Build Coastguard Worker    {
92*1b3f573fSAndroid Build Coastguard Worker      GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
93*1b3f573fSAndroid Build Coastguard Worker      XCTAssertEqual((int32_t)value, [input readInt32]);
94*1b3f573fSAndroid Build Coastguard Worker    }
95*1b3f573fSAndroid Build Coastguard Worker    {
96*1b3f573fSAndroid Build Coastguard Worker      GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
97*1b3f573fSAndroid Build Coastguard Worker      XCTAssertEqual((int32_t)value, [input readEnum]);
98*1b3f573fSAndroid Build Coastguard Worker    }
99*1b3f573fSAndroid Build Coastguard Worker  }
100*1b3f573fSAndroid Build Coastguard Worker  if (value <= UINT32_MAX && value >= 0) {
101*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
102*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual((uint32_t)value, [input readUInt32]);
103*1b3f573fSAndroid Build Coastguard Worker  }
104*1b3f573fSAndroid Build Coastguard Worker  {
105*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
106*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value, [input readInt64]);
107*1b3f573fSAndroid Build Coastguard Worker  }
108*1b3f573fSAndroid Build Coastguard Worker  if (value >= 0) {
109*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
110*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual((uint64_t)value, [input readUInt64]);
111*1b3f573fSAndroid Build Coastguard Worker  }
112*1b3f573fSAndroid Build Coastguard Worker}
113*1b3f573fSAndroid Build Coastguard Worker
114*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value {
115*1b3f573fSAndroid Build Coastguard Worker  {
116*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
117*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value, [input readSFixed32]);
118*1b3f573fSAndroid Build Coastguard Worker  }
119*1b3f573fSAndroid Build Coastguard Worker  {
120*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
121*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(GPBConvertInt32ToFloat(value), [input readFloat]);
122*1b3f573fSAndroid Build Coastguard Worker  }
123*1b3f573fSAndroid Build Coastguard Worker  {
124*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
125*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual((uint32_t)value, [input readFixed32]);
126*1b3f573fSAndroid Build Coastguard Worker  }
127*1b3f573fSAndroid Build Coastguard Worker  {
128*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
129*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value, [input readSFixed32]);
130*1b3f573fSAndroid Build Coastguard Worker  }
131*1b3f573fSAndroid Build Coastguard Worker}
132*1b3f573fSAndroid Build Coastguard Worker
133*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value {
134*1b3f573fSAndroid Build Coastguard Worker  {
135*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
136*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value, [input readSFixed64]);
137*1b3f573fSAndroid Build Coastguard Worker  }
138*1b3f573fSAndroid Build Coastguard Worker  {
139*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
140*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(GPBConvertInt64ToDouble(value), [input readDouble]);
141*1b3f573fSAndroid Build Coastguard Worker  }
142*1b3f573fSAndroid Build Coastguard Worker  {
143*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
144*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual((uint64_t)value, [input readFixed64]);
145*1b3f573fSAndroid Build Coastguard Worker  }
146*1b3f573fSAndroid Build Coastguard Worker  {
147*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
148*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value, [input readSFixed64]);
149*1b3f573fSAndroid Build Coastguard Worker  }
150*1b3f573fSAndroid Build Coastguard Worker}
151*1b3f573fSAndroid Build Coastguard Worker
152*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadZigZag32:(NSData*)data value:(int64_t)value {
153*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
154*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual((int32_t)value, [input readSInt32]);
155*1b3f573fSAndroid Build Coastguard Worker}
156*1b3f573fSAndroid Build Coastguard Worker
157*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadZigZag64:(NSData*)data value:(int64_t)value {
158*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
159*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(value, [input readSInt64]);
160*1b3f573fSAndroid Build Coastguard Worker}
161*1b3f573fSAndroid Build Coastguard Worker
162*1b3f573fSAndroid Build Coastguard Worker- (void)assertReadVarintFailure:(NSData*)data {
163*1b3f573fSAndroid Build Coastguard Worker  {
164*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
165*1b3f573fSAndroid Build Coastguard Worker    XCTAssertThrows([input readInt32]);
166*1b3f573fSAndroid Build Coastguard Worker  }
167*1b3f573fSAndroid Build Coastguard Worker  {
168*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
169*1b3f573fSAndroid Build Coastguard Worker    XCTAssertThrows([input readInt64]);
170*1b3f573fSAndroid Build Coastguard Worker  }
171*1b3f573fSAndroid Build Coastguard Worker}
172*1b3f573fSAndroid Build Coastguard Worker
173*1b3f573fSAndroid Build Coastguard Worker- (void)testBytes {
174*1b3f573fSAndroid Build Coastguard Worker  NSData* data = bytes(0xa2, 0x74);
175*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(data.length, (NSUInteger)2);
176*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(((uint8_t*)data.bytes)[0], (uint8_t)0xa2);
177*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74);
178*1b3f573fSAndroid Build Coastguard Worker}
179*1b3f573fSAndroid Build Coastguard Worker
180*1b3f573fSAndroid Build Coastguard Worker- (void)testReadBool {
181*1b3f573fSAndroid Build Coastguard Worker  {
182*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x00)];
183*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(NO, [input readBool]);
184*1b3f573fSAndroid Build Coastguard Worker  }
185*1b3f573fSAndroid Build Coastguard Worker  {
186*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:bytes(0x01)];
187*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(YES, [input readBool]);
188*1b3f573fSAndroid Build Coastguard Worker  }
189*1b3f573fSAndroid Build Coastguard Worker}
190*1b3f573fSAndroid Build Coastguard Worker
191*1b3f573fSAndroid Build Coastguard Worker- (void)testReadVarint {
192*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0x00) value:0];
193*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0x01) value:1];
194*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0x7f) value:127];
195*1b3f573fSAndroid Build Coastguard Worker  // 14882
196*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
197*1b3f573fSAndroid Build Coastguard Worker  // 1904930
198*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0xa2, 0xa2, 0x74) value:(0x22 << 0) | (0x22 << 7) | (0x74 << 14)];
199*1b3f573fSAndroid Build Coastguard Worker  // 243831074
200*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0xa2, 0xa2, 0xa2, 0x74)
201*1b3f573fSAndroid Build Coastguard Worker                   value:(0x22 << 0) | (0x22 << 7) | (0x22 << 14) | (0x74 << 21)];
202*1b3f573fSAndroid Build Coastguard Worker  // 2961488830
203*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
204*1b3f573fSAndroid Build Coastguard Worker                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
205*1b3f573fSAndroid Build Coastguard Worker                         (0x04 << 21) | (0x0bLL << 28)];
206*1b3f573fSAndroid Build Coastguard Worker
207*1b3f573fSAndroid Build Coastguard Worker  // 64-bit
208*1b3f573fSAndroid Build Coastguard Worker  // 7256456126
209*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
210*1b3f573fSAndroid Build Coastguard Worker                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
211*1b3f573fSAndroid Build Coastguard Worker                         (0x04 << 21) | (0x1bLL << 28)];
212*1b3f573fSAndroid Build Coastguard Worker  // 41256202580718336
213*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
214*1b3f573fSAndroid Build Coastguard Worker                   value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
215*1b3f573fSAndroid Build Coastguard Worker                         (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
216*1b3f573fSAndroid Build Coastguard Worker                         (0x24LL << 42) | (0x49LL << 49)];
217*1b3f573fSAndroid Build Coastguard Worker  // 11964378330978735131
218*1b3f573fSAndroid Build Coastguard Worker  [self
219*1b3f573fSAndroid Build Coastguard Worker      assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
220*1b3f573fSAndroid Build Coastguard Worker                             0xa6, 0x01)
221*1b3f573fSAndroid Build Coastguard Worker                 value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
222*1b3f573fSAndroid Build Coastguard Worker                       (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) |
223*1b3f573fSAndroid Build Coastguard Worker                       (0x05LL << 49) | (0x26LL << 56) | (0x01ULL << 63)];
224*1b3f573fSAndroid Build Coastguard Worker
225*1b3f573fSAndroid Build Coastguard Worker  // Failures
226*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
227*1b3f573fSAndroid Build Coastguard Worker                                      0x80, 0x80, 0x80, 0x00)];
228*1b3f573fSAndroid Build Coastguard Worker  [self assertReadVarintFailure:bytes(0x80)];
229*1b3f573fSAndroid Build Coastguard Worker}
230*1b3f573fSAndroid Build Coastguard Worker
231*1b3f573fSAndroid Build Coastguard Worker- (void)testReadVarint32FromVarint64 {
232*1b3f573fSAndroid Build Coastguard Worker  {
233*1b3f573fSAndroid Build Coastguard Worker    // Turn on lower 31 bits of the upper half on a 64 bit varint.
234*1b3f573fSAndroid Build Coastguard Worker    NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E);
235*1b3f573fSAndroid Build Coastguard Worker
236*1b3f573fSAndroid Build Coastguard Worker    int32_t value32 = 0x0;
237*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
238*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value32, [input32 readInt32]);
239*1b3f573fSAndroid Build Coastguard Worker
240*1b3f573fSAndroid Build Coastguard Worker    int64_t value64 = INT64_MAX & 0xFFFFFFFF00000000;
241*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
242*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value64, [input64 readInt64]);
243*1b3f573fSAndroid Build Coastguard Worker  }
244*1b3f573fSAndroid Build Coastguard Worker  {
245*1b3f573fSAndroid Build Coastguard Worker    // Turn on lower 31 bits and lower 31 bits on upper half on a 64 bit varint.
246*1b3f573fSAndroid Build Coastguard Worker    NSData* data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E);
247*1b3f573fSAndroid Build Coastguard Worker
248*1b3f573fSAndroid Build Coastguard Worker    int32_t value32 = INT32_MAX;
249*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
250*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value32, [input32 readInt32]);
251*1b3f573fSAndroid Build Coastguard Worker
252*1b3f573fSAndroid Build Coastguard Worker    int64_t value64 = INT64_MAX & 0xFFFFFFFF7FFFFFFF;
253*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
254*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value64, [input64 readInt64]);
255*1b3f573fSAndroid Build Coastguard Worker  }
256*1b3f573fSAndroid Build Coastguard Worker  {
257*1b3f573fSAndroid Build Coastguard Worker    // Turn on bits 32 and 64 bit on a 64 bit varint.
258*1b3f573fSAndroid Build Coastguard Worker    NSData* data = bytes(0x80, 0x80, 0x80, 0x80, 0x88, 0x80, 0x80, 0x80, 0x80, 0x01);
259*1b3f573fSAndroid Build Coastguard Worker
260*1b3f573fSAndroid Build Coastguard Worker    int32_t value32 = INT32_MIN;
261*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input32 = [GPBCodedInputStream streamWithData:data];
262*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value32, [input32 readInt32]);
263*1b3f573fSAndroid Build Coastguard Worker
264*1b3f573fSAndroid Build Coastguard Worker    int64_t value64 = INT64_MIN | (0x01LL << 31);
265*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input64 = [GPBCodedInputStream streamWithData:data];
266*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(value64, [input64 readInt64]);
267*1b3f573fSAndroid Build Coastguard Worker  }
268*1b3f573fSAndroid Build Coastguard Worker}
269*1b3f573fSAndroid Build Coastguard Worker
270*1b3f573fSAndroid Build Coastguard Worker- (void)testReadLittleEndian {
271*1b3f573fSAndroid Build Coastguard Worker  [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
272*1b3f573fSAndroid Build Coastguard Worker                           value:0x12345678];
273*1b3f573fSAndroid Build Coastguard Worker  [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
274*1b3f573fSAndroid Build Coastguard Worker                           value:0x9abcdef0];
275*1b3f573fSAndroid Build Coastguard Worker
276*1b3f573fSAndroid Build Coastguard Worker  [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34,
277*1b3f573fSAndroid Build Coastguard Worker                                       0x12)
278*1b3f573fSAndroid Build Coastguard Worker                           value:0x123456789abcdef0LL];
279*1b3f573fSAndroid Build Coastguard Worker  [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc,
280*1b3f573fSAndroid Build Coastguard Worker                                       0x9a)
281*1b3f573fSAndroid Build Coastguard Worker                           value:0x9abcdef012345678LL];
282*1b3f573fSAndroid Build Coastguard Worker}
283*1b3f573fSAndroid Build Coastguard Worker
284*1b3f573fSAndroid Build Coastguard Worker- (void)testReadWholeMessage {
285*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
286*1b3f573fSAndroid Build Coastguard Worker
287*1b3f573fSAndroid Build Coastguard Worker  NSData* rawBytes = message.data;
288*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
289*1b3f573fSAndroid Build Coastguard Worker
290*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message2 =
291*1b3f573fSAndroid Build Coastguard Worker      [TestAllTypes parseFromData:rawBytes extensionRegistry:nil error:NULL];
292*1b3f573fSAndroid Build Coastguard Worker  [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
293*1b3f573fSAndroid Build Coastguard Worker}
294*1b3f573fSAndroid Build Coastguard Worker
295*1b3f573fSAndroid Build Coastguard Worker- (void)testSkipWholeMessage {
296*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
297*1b3f573fSAndroid Build Coastguard Worker  NSData* rawBytes = message.data;
298*1b3f573fSAndroid Build Coastguard Worker
299*1b3f573fSAndroid Build Coastguard Worker  // Create two parallel inputs.  Parse one as unknown fields while using
300*1b3f573fSAndroid Build Coastguard Worker  // skipField() to skip each field on the other.  Expect the same tags.
301*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
302*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
303*1b3f573fSAndroid Build Coastguard Worker  GPBUnknownFieldSet* unknownFields =
304*1b3f573fSAndroid Build Coastguard Worker      [[[GPBUnknownFieldSet alloc] init] autorelease];
305*1b3f573fSAndroid Build Coastguard Worker
306*1b3f573fSAndroid Build Coastguard Worker  while (YES) {
307*1b3f573fSAndroid Build Coastguard Worker    int32_t tag = [input1 readTag];
308*1b3f573fSAndroid Build Coastguard Worker    XCTAssertEqual(tag, [input2 readTag]);
309*1b3f573fSAndroid Build Coastguard Worker    if (tag == 0) {
310*1b3f573fSAndroid Build Coastguard Worker      break;
311*1b3f573fSAndroid Build Coastguard Worker    }
312*1b3f573fSAndroid Build Coastguard Worker    [unknownFields mergeFieldFrom:tag input:input1];
313*1b3f573fSAndroid Build Coastguard Worker    [input2 skipField:tag];
314*1b3f573fSAndroid Build Coastguard Worker  }
315*1b3f573fSAndroid Build Coastguard Worker}
316*1b3f573fSAndroid Build Coastguard Worker
317*1b3f573fSAndroid Build Coastguard Worker- (void)testReadHugeBlob {
318*1b3f573fSAndroid Build Coastguard Worker  // Allocate and initialize a 1MB blob.
319*1b3f573fSAndroid Build Coastguard Worker  NSMutableData* blob = [NSMutableData dataWithLength:1 << 20];
320*1b3f573fSAndroid Build Coastguard Worker  for (NSUInteger i = 0; i < blob.length; i++) {
321*1b3f573fSAndroid Build Coastguard Worker    ((uint8_t*)blob.mutableBytes)[i] = (uint8_t)i;
322*1b3f573fSAndroid Build Coastguard Worker  }
323*1b3f573fSAndroid Build Coastguard Worker
324*1b3f573fSAndroid Build Coastguard Worker  // Make a message containing it.
325*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message = [TestAllTypes message];
326*1b3f573fSAndroid Build Coastguard Worker  [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
327*1b3f573fSAndroid Build Coastguard Worker  [message setOptionalBytes:blob];
328*1b3f573fSAndroid Build Coastguard Worker
329*1b3f573fSAndroid Build Coastguard Worker  // Serialize and parse it.  Make sure to parse from an InputStream, not
330*1b3f573fSAndroid Build Coastguard Worker  // directly from a ByteString, so that CodedInputStream uses buffered
331*1b3f573fSAndroid Build Coastguard Worker  // reading.
332*1b3f573fSAndroid Build Coastguard Worker  NSData *messageData = message.data;
333*1b3f573fSAndroid Build Coastguard Worker  XCTAssertNotNil(messageData);
334*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* stream =
335*1b3f573fSAndroid Build Coastguard Worker      [GPBCodedInputStream streamWithData:messageData];
336*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message2 = [TestAllTypes parseFromCodedInputStream:stream
337*1b3f573fSAndroid Build Coastguard Worker                                                 extensionRegistry:nil
338*1b3f573fSAndroid Build Coastguard Worker                                                             error:NULL];
339*1b3f573fSAndroid Build Coastguard Worker
340*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqualObjects(message.optionalBytes, message2.optionalBytes);
341*1b3f573fSAndroid Build Coastguard Worker
342*1b3f573fSAndroid Build Coastguard Worker  // Make sure all the other fields were parsed correctly.
343*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message3 = [[message2 copy] autorelease];
344*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* types = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
345*1b3f573fSAndroid Build Coastguard Worker  NSData* data = [types optionalBytes];
346*1b3f573fSAndroid Build Coastguard Worker  [message3 setOptionalBytes:data];
347*1b3f573fSAndroid Build Coastguard Worker
348*1b3f573fSAndroid Build Coastguard Worker  [self assertAllFieldsSet:message3 repeatedCount:kGPBDefaultRepeatCount];
349*1b3f573fSAndroid Build Coastguard Worker}
350*1b3f573fSAndroid Build Coastguard Worker
351*1b3f573fSAndroid Build Coastguard Worker- (void)testReadMaliciouslyLargeBlob {
352*1b3f573fSAndroid Build Coastguard Worker  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
353*1b3f573fSAndroid Build Coastguard Worker  GPBCodedOutputStream* output =
354*1b3f573fSAndroid Build Coastguard Worker      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
355*1b3f573fSAndroid Build Coastguard Worker
356*1b3f573fSAndroid Build Coastguard Worker  int32_t tag = GPBWireFormatMakeTag(1, GPBWireFormatLengthDelimited);
357*1b3f573fSAndroid Build Coastguard Worker  [output writeRawVarint32:tag];
358*1b3f573fSAndroid Build Coastguard Worker  [output writeRawVarint32:0x7FFFFFFF];
359*1b3f573fSAndroid Build Coastguard Worker  uint8_t bytes[32] = {0};
360*1b3f573fSAndroid Build Coastguard Worker  [output writeRawData:[NSData dataWithBytes:bytes length:32]];
361*1b3f573fSAndroid Build Coastguard Worker  [output flush];
362*1b3f573fSAndroid Build Coastguard Worker
363*1b3f573fSAndroid Build Coastguard Worker  NSData* data =
364*1b3f573fSAndroid Build Coastguard Worker      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
365*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input =
366*1b3f573fSAndroid Build Coastguard Worker      [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
367*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqual(tag, [input readTag]);
368*1b3f573fSAndroid Build Coastguard Worker
369*1b3f573fSAndroid Build Coastguard Worker  XCTAssertThrows([input readBytes]);
370*1b3f573fSAndroid Build Coastguard Worker}
371*1b3f573fSAndroid Build Coastguard Worker
372*1b3f573fSAndroid Build Coastguard Worker- (void)testReadEmptyString {
373*1b3f573fSAndroid Build Coastguard Worker  NSData *data = bytes(0x00);
374*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
375*1b3f573fSAndroid Build Coastguard Worker  XCTAssertEqualObjects(@"", [input readString]);
376*1b3f573fSAndroid Build Coastguard Worker}
377*1b3f573fSAndroid Build Coastguard Worker
378*1b3f573fSAndroid Build Coastguard Worker- (void)testInvalidGroupEndTagThrows {
379*1b3f573fSAndroid Build Coastguard Worker  NSData *data = bytes(0x0B, 0x1A, 0x02, 0x4B, 0x50, 0x14);
380*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
381*1b3f573fSAndroid Build Coastguard Worker  XCTAssertThrowsSpecificNamed([input skipMessage],
382*1b3f573fSAndroid Build Coastguard Worker                               NSException,
383*1b3f573fSAndroid Build Coastguard Worker                               GPBCodedInputStreamException,
384*1b3f573fSAndroid Build Coastguard Worker                               @"should throw a GPBCodedInputStreamException exception ");
385*1b3f573fSAndroid Build Coastguard Worker}
386*1b3f573fSAndroid Build Coastguard Worker
387*1b3f573fSAndroid Build Coastguard Worker- (void)testBytesWithNegativeSize {
388*1b3f573fSAndroid Build Coastguard Worker  NSData *data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F);
389*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data];
390*1b3f573fSAndroid Build Coastguard Worker  XCTAssertNil([input readBytes]);
391*1b3f573fSAndroid Build Coastguard Worker}
392*1b3f573fSAndroid Build Coastguard Worker
393*1b3f573fSAndroid Build Coastguard Worker// Verifies fix for b/10315336.
394*1b3f573fSAndroid Build Coastguard Worker// Note: Now that there isn't a custom string class under the hood, this test
395*1b3f573fSAndroid Build Coastguard Worker// isn't as critical, but it does cover bad input and if a custom class is added
396*1b3f573fSAndroid Build Coastguard Worker// again, it will help validate that class' handing of bad utf8.
397*1b3f573fSAndroid Build Coastguard Worker- (void)testReadMalformedString {
398*1b3f573fSAndroid Build Coastguard Worker  NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
399*1b3f573fSAndroid Build Coastguard Worker  GPBCodedOutputStream* output =
400*1b3f573fSAndroid Build Coastguard Worker      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
401*1b3f573fSAndroid Build Coastguard Worker
402*1b3f573fSAndroid Build Coastguard Worker  int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
403*1b3f573fSAndroid Build Coastguard Worker                                     GPBWireFormatLengthDelimited);
404*1b3f573fSAndroid Build Coastguard Worker  [output writeRawVarint32:tag];
405*1b3f573fSAndroid Build Coastguard Worker  [output writeRawVarint32:5];
406*1b3f573fSAndroid Build Coastguard Worker  // Create an invalid utf-8 byte array.
407*1b3f573fSAndroid Build Coastguard Worker  uint8_t bytes[] = {0xc2, 0xf2, 0x0, 0x0, 0x0};
408*1b3f573fSAndroid Build Coastguard Worker  [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
409*1b3f573fSAndroid Build Coastguard Worker  [output flush];
410*1b3f573fSAndroid Build Coastguard Worker
411*1b3f573fSAndroid Build Coastguard Worker  NSData *data =
412*1b3f573fSAndroid Build Coastguard Worker      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
413*1b3f573fSAndroid Build Coastguard Worker  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
414*1b3f573fSAndroid Build Coastguard Worker  NSError *error = nil;
415*1b3f573fSAndroid Build Coastguard Worker  TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
416*1b3f573fSAndroid Build Coastguard Worker                                                extensionRegistry:nil
417*1b3f573fSAndroid Build Coastguard Worker                                                            error:&error];
418*1b3f573fSAndroid Build Coastguard Worker  XCTAssertNotNil(error);
419*1b3f573fSAndroid Build Coastguard Worker  XCTAssertNil(message);
420*1b3f573fSAndroid Build Coastguard Worker}
421*1b3f573fSAndroid Build Coastguard Worker
422*1b3f573fSAndroid Build Coastguard Worker- (void)testBOMWithinStrings {
423*1b3f573fSAndroid Build Coastguard Worker  // We've seen servers that end up with BOMs within strings (not always at the
424*1b3f573fSAndroid Build Coastguard Worker  // start, and sometimes in multiple places), make sure they always parse
425*1b3f573fSAndroid Build Coastguard Worker  // correctly. (Again, this is inpart in case a custom string class is ever
426*1b3f573fSAndroid Build Coastguard Worker  // used again.)
427*1b3f573fSAndroid Build Coastguard Worker  const char* strs[] = {
428*1b3f573fSAndroid Build Coastguard Worker    "\xEF\xBB\xBF String with BOM",
429*1b3f573fSAndroid Build Coastguard Worker    "String with \xEF\xBB\xBF in middle",
430*1b3f573fSAndroid Build Coastguard Worker    "String with end bom \xEF\xBB\xBF",
431*1b3f573fSAndroid Build Coastguard Worker    "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart
432*1b3f573fSAndroid Build Coastguard Worker    "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
433*1b3f573fSAndroid Build Coastguard Worker  };
434*1b3f573fSAndroid Build Coastguard Worker  for (size_t i = 0; i < GPBARRAYSIZE(strs); ++i) {
435*1b3f573fSAndroid Build Coastguard Worker    NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
436*1b3f573fSAndroid Build Coastguard Worker    GPBCodedOutputStream* output =
437*1b3f573fSAndroid Build Coastguard Worker        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
438*1b3f573fSAndroid Build Coastguard Worker
439*1b3f573fSAndroid Build Coastguard Worker    int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
440*1b3f573fSAndroid Build Coastguard Worker                                       GPBWireFormatLengthDelimited);
441*1b3f573fSAndroid Build Coastguard Worker    [output writeRawVarint32:tag];
442*1b3f573fSAndroid Build Coastguard Worker    size_t length = strlen(strs[i]);
443*1b3f573fSAndroid Build Coastguard Worker    [output writeRawVarint32:(int32_t)length];
444*1b3f573fSAndroid Build Coastguard Worker    [output writeRawData:[NSData dataWithBytes:strs[i] length:length]];
445*1b3f573fSAndroid Build Coastguard Worker    [output flush];
446*1b3f573fSAndroid Build Coastguard Worker
447*1b3f573fSAndroid Build Coastguard Worker    NSData* data =
448*1b3f573fSAndroid Build Coastguard Worker        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
449*1b3f573fSAndroid Build Coastguard Worker    GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
450*1b3f573fSAndroid Build Coastguard Worker    TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
451*1b3f573fSAndroid Build Coastguard Worker                                                  extensionRegistry:nil
452*1b3f573fSAndroid Build Coastguard Worker                                                              error:NULL];
453*1b3f573fSAndroid Build Coastguard Worker    XCTAssertNotNil(message, @"Loop %zd", i);
454*1b3f573fSAndroid Build Coastguard Worker    // Ensure the string is there. NSString can consume the BOM in some
455*1b3f573fSAndroid Build Coastguard Worker    // cases, so don't actually check the string for exact equality.
456*1b3f573fSAndroid Build Coastguard Worker    XCTAssertTrue(message.defaultString.length > 0, @"Loop %zd", i);
457*1b3f573fSAndroid Build Coastguard Worker  }
458*1b3f573fSAndroid Build Coastguard Worker}
459*1b3f573fSAndroid Build Coastguard Worker
460*1b3f573fSAndroid Build Coastguard Worker@end
461