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