Home | History | Annotate | Download | only in Tests
      1 // Protocol Buffers - Google's data interchange format
      2 // Copyright 2008 Google Inc.  All rights reserved.
      3 // https://developers.google.com/protocol-buffers/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are
      7 // met:
      8 //
      9 //     * Redistributions of source code must retain the above copyright
     10 // notice, this list of conditions and the following disclaimer.
     11 //     * Redistributions in binary form must reproduce the above
     12 // copyright notice, this list of conditions and the following disclaimer
     13 // in the documentation and/or other materials provided with the
     14 // distribution.
     15 //     * Neither the name of Google Inc. nor the names of its
     16 // contributors may be used to endorse or promote products derived from
     17 // this software without specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 #import "GPBTestUtilities.h"
     32 
     33 #import "GPBCodedOutputStream_PackagePrivate.h"
     34 #import "GPBCodedInputStream.h"
     35 #import "GPBUtilities_PackagePrivate.h"
     36 #import "google/protobuf/Unittest.pbobjc.h"
     37 
     38 @interface GPBCodedOutputStream (InternalMethods)
     39 // Declared in the .m file, expose for testing.
     40 - (instancetype)initWithOutputStream:(NSOutputStream *)output
     41                                 data:(NSMutableData *)data;
     42 @end
     43 
     44 @interface GPBCodedOutputStream (Helper)
     45 + (instancetype)streamWithOutputStream:(NSOutputStream *)output
     46                             bufferSize:(size_t)bufferSize;
     47 @end
     48 
     49 @implementation GPBCodedOutputStream (Helper)
     50 + (instancetype)streamWithOutputStream:(NSOutputStream *)output
     51                             bufferSize:(size_t)bufferSize {
     52   NSMutableData *data = [NSMutableData dataWithLength:bufferSize];
     53   return [[[self alloc] initWithOutputStream:output data:data] autorelease];
     54 }
     55 @end
     56 
     57 @interface CodedOutputStreamTests : GPBTestCase
     58 @end
     59 
     60 @implementation CodedOutputStreamTests
     61 
     62 - (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
     63   va_list list;
     64   va_start(list, unused);
     65 
     66   NSMutableData* values = [NSMutableData dataWithCapacity:0];
     67   int32_t i;
     68 
     69   while ((i = va_arg(list, int32_t)) != 256) {
     70     NSAssert(i >= 0 && i < 256, @"");
     71     uint8_t u = (uint8_t)i;
     72     [values appendBytes:&u length:1];
     73   }
     74 
     75   va_end(list);
     76 
     77   return values;
     78 }
     79 
     80 #define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
     81 
     82 - (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value {
     83   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
     84   GPBCodedOutputStream* output =
     85       [GPBCodedOutputStream streamWithOutputStream:rawOutput];
     86   [output writeRawLittleEndian32:(int32_t)value];
     87   [output flush];
     88 
     89   NSData* actual =
     90       [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
     91   XCTAssertEqualObjects(data, actual);
     92 
     93   // Try different block sizes.
     94   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
     95     rawOutput = [NSOutputStream outputStreamToMemory];
     96     output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
     97                                                bufferSize:blockSize];
     98     [output writeRawLittleEndian32:(int32_t)value];
     99     [output flush];
    100 
    101     actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    102     XCTAssertEqualObjects(data, actual);
    103   }
    104 }
    105 
    106 - (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value {
    107   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    108   GPBCodedOutputStream* output =
    109       [GPBCodedOutputStream streamWithOutputStream:rawOutput];
    110   [output writeRawLittleEndian64:value];
    111   [output flush];
    112 
    113   NSData* actual =
    114       [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    115   XCTAssertEqualObjects(data, actual);
    116 
    117   // Try different block sizes.
    118   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
    119     rawOutput = [NSOutputStream outputStreamToMemory];
    120     output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
    121                                                bufferSize:blockSize];
    122     [output writeRawLittleEndian64:value];
    123     [output flush];
    124 
    125     actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    126     XCTAssertEqualObjects(data, actual);
    127   }
    128 }
    129 
    130 - (void)assertWriteVarint:(NSData*)data value:(int64_t)value {
    131   // Only do 32-bit write if the value fits in 32 bits.
    132   if (GPBLogicalRightShift64(value, 32) == 0) {
    133     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    134     GPBCodedOutputStream* output =
    135         [GPBCodedOutputStream streamWithOutputStream:rawOutput];
    136     [output writeRawVarint32:(int32_t)value];
    137     [output flush];
    138 
    139     NSData* actual =
    140         [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    141     XCTAssertEqualObjects(data, actual);
    142 
    143     // Also try computing size.
    144     XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value),
    145                    (size_t)data.length);
    146   }
    147 
    148   {
    149     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    150     GPBCodedOutputStream* output =
    151         [GPBCodedOutputStream streamWithOutputStream:rawOutput];
    152     [output writeRawVarint64:value];
    153     [output flush];
    154 
    155     NSData* actual =
    156         [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    157     XCTAssertEqualObjects(data, actual);
    158 
    159     // Also try computing size.
    160     XCTAssertEqual(GPBComputeRawVarint64Size(value), (size_t)data.length);
    161   }
    162 
    163   // Try different block sizes.
    164   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
    165     // Only do 32-bit write if the value fits in 32 bits.
    166     if (GPBLogicalRightShift64(value, 32) == 0) {
    167       NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    168       GPBCodedOutputStream* output =
    169           [GPBCodedOutputStream streamWithOutputStream:rawOutput
    170                                             bufferSize:blockSize];
    171 
    172       [output writeRawVarint32:(int32_t)value];
    173       [output flush];
    174 
    175       NSData* actual =
    176           [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    177       XCTAssertEqualObjects(data, actual);
    178     }
    179 
    180     {
    181       NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    182       GPBCodedOutputStream* output =
    183           [GPBCodedOutputStream streamWithOutputStream:rawOutput
    184                                             bufferSize:blockSize];
    185 
    186       [output writeRawVarint64:value];
    187       [output flush];
    188 
    189       NSData* actual =
    190           [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    191       XCTAssertEqualObjects(data, actual);
    192     }
    193   }
    194 }
    195 
    196 - (void)testWriteVarint1 {
    197   [self assertWriteVarint:bytes(0x00) value:0];
    198 }
    199 
    200 - (void)testWriteVarint2 {
    201   [self assertWriteVarint:bytes(0x01) value:1];
    202 }
    203 
    204 - (void)testWriteVarint3 {
    205   [self assertWriteVarint:bytes(0x7f) value:127];
    206 }
    207 
    208 - (void)testWriteVarint4 {
    209   // 14882
    210   [self assertWriteVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
    211 }
    212 
    213 - (void)testWriteVarint5 {
    214   // 2961488830
    215   [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
    216                     value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
    217                           (0x04 << 21) | (0x0bLL << 28)];
    218 }
    219 
    220 - (void)testWriteVarint6 {
    221   // 64-bit
    222   // 7256456126
    223   [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
    224                     value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
    225                           (0x04 << 21) | (0x1bLL << 28)];
    226 }
    227 
    228 - (void)testWriteVarint7 {
    229   // 41256202580718336
    230   [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
    231                     value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
    232                           (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
    233                           (0x24LL << 42) | (0x49LL << 49)];
    234 }
    235 
    236 - (void)testWriteVarint8 {
    237   // 11964378330978735131
    238   [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
    239                                 0xa6, 0x01)
    240                     value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) |
    241                           (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) |
    242                           (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
    243                           (0x01LL << 63)];
    244 }
    245 
    246 - (void)testWriteLittleEndian {
    247   [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
    248                             value:0x12345678];
    249   [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
    250                             value:0x9abcdef0];
    251 
    252   [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
    253                                         0x34, 0x12)
    254                             value:0x123456789abcdef0LL];
    255   [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde,
    256                                         0xbc, 0x9a)
    257                             value:0x9abcdef012345678LL];
    258 }
    259 
    260 - (void)testEncodeZigZag {
    261   XCTAssertEqual(0U, GPBEncodeZigZag32(0));
    262   XCTAssertEqual(1U, GPBEncodeZigZag32(-1));
    263   XCTAssertEqual(2U, GPBEncodeZigZag32(1));
    264   XCTAssertEqual(3U, GPBEncodeZigZag32(-2));
    265   XCTAssertEqual(0x7FFFFFFEU, GPBEncodeZigZag32(0x3FFFFFFF));
    266   XCTAssertEqual(0x7FFFFFFFU, GPBEncodeZigZag32(0xC0000000));
    267   XCTAssertEqual(0xFFFFFFFEU, GPBEncodeZigZag32(0x7FFFFFFF));
    268   XCTAssertEqual(0xFFFFFFFFU, GPBEncodeZigZag32(0x80000000));
    269 
    270   XCTAssertEqual(0ULL, GPBEncodeZigZag64(0));
    271   XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1));
    272   XCTAssertEqual(2ULL, GPBEncodeZigZag64(1));
    273   XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2));
    274   XCTAssertEqual(0x000000007FFFFFFEULL,
    275                  GPBEncodeZigZag64(0x000000003FFFFFFFLL));
    276   XCTAssertEqual(0x000000007FFFFFFFULL,
    277                  GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
    278   XCTAssertEqual(0x00000000FFFFFFFEULL,
    279                  GPBEncodeZigZag64(0x000000007FFFFFFFLL));
    280   XCTAssertEqual(0x00000000FFFFFFFFULL,
    281                  GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
    282   XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL,
    283                  GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
    284   XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL,
    285                  GPBEncodeZigZag64(0x8000000000000000LL));
    286 
    287   // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
    288   // were chosen semi-randomly via keyboard bashing.
    289   XCTAssertEqual(0U, GPBEncodeZigZag32(GPBDecodeZigZag32(0)));
    290   XCTAssertEqual(1U, GPBEncodeZigZag32(GPBDecodeZigZag32(1)));
    291   XCTAssertEqual(-1U, GPBEncodeZigZag32(GPBDecodeZigZag32(-1)));
    292   XCTAssertEqual(14927U, GPBEncodeZigZag32(GPBDecodeZigZag32(14927)));
    293   XCTAssertEqual(-3612U, GPBEncodeZigZag32(GPBDecodeZigZag32(-3612)));
    294 
    295   XCTAssertEqual(0ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(0)));
    296   XCTAssertEqual(1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(1)));
    297   XCTAssertEqual(-1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-1)));
    298   XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927)));
    299   XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612)));
    300 
    301   XCTAssertEqual(856912304801416ULL,
    302                  GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
    303   XCTAssertEqual(-75123905439571256ULL,
    304                  GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
    305 }
    306 
    307 - (void)testWriteWholeMessage {
    308   // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
    309   // that was generated with 2.
    310   TestAllTypes* message = [self allSetRepeatedCount:2];
    311 
    312   NSData* rawBytes = message.data;
    313   NSData* goldenData =
    314       [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
    315   XCTAssertEqualObjects(rawBytes, goldenData);
    316 
    317   // Try different block sizes.
    318   for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
    319     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
    320     GPBCodedOutputStream* output =
    321         [GPBCodedOutputStream streamWithOutputStream:rawOutput
    322                                           bufferSize:blockSize];
    323     [message writeToCodedOutputStream:output];
    324     [output flush];
    325 
    326     NSData* actual =
    327         [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
    328     XCTAssertEqualObjects(rawBytes, actual);
    329   }
    330 
    331   // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
    332   // that was generated with 2.
    333   TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2];
    334   rawBytes = extensions.data;
    335   goldenData = [self getDataFileNamed:@"golden_packed_fields_message"
    336                           dataToWrite:rawBytes];
    337   XCTAssertEqualObjects(rawBytes, goldenData);
    338 }
    339 
    340 @end
    341