OLD | NEW |
| (Empty) |
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.h" | |
34 #import "GPBCodedInputStream.h" | |
35 #import "GPBUtilities_PackagePrivate.h" | |
36 #import "google/protobuf/Unittest.pbobjc.h" | |
37 | |
38 @interface CodedOutputStreamTests : GPBTestCase | |
39 @end | |
40 | |
41 @implementation CodedOutputStreamTests | |
42 | |
43 - (NSData*)bytes_with_sentinel:(int32_t)unused, ... { | |
44 va_list list; | |
45 va_start(list, unused); | |
46 | |
47 NSMutableData* values = [NSMutableData dataWithCapacity:0]; | |
48 int32_t i; | |
49 | |
50 while ((i = va_arg(list, int32_t)) != 256) { | |
51 NSAssert(i >= 0 && i < 256, @""); | |
52 uint8_t u = (uint8_t)i; | |
53 [values appendBytes:&u length:1]; | |
54 } | |
55 | |
56 va_end(list); | |
57 | |
58 return values; | |
59 } | |
60 | |
61 #define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256] | |
62 | |
63 - (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value { | |
64 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
65 GPBCodedOutputStream* output = | |
66 [GPBCodedOutputStream streamWithOutputStream:rawOutput]; | |
67 [output writeRawLittleEndian32:(int32_t)value]; | |
68 [output flush]; | |
69 | |
70 NSData* actual = | |
71 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
72 XCTAssertEqualObjects(data, actual); | |
73 | |
74 // Try different block sizes. | |
75 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { | |
76 rawOutput = [NSOutputStream outputStreamToMemory]; | |
77 output = [GPBCodedOutputStream streamWithOutputStream:rawOutput | |
78 bufferSize:blockSize]; | |
79 [output writeRawLittleEndian32:(int32_t)value]; | |
80 [output flush]; | |
81 | |
82 actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
83 XCTAssertEqualObjects(data, actual); | |
84 } | |
85 } | |
86 | |
87 - (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value { | |
88 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
89 GPBCodedOutputStream* output = | |
90 [GPBCodedOutputStream streamWithOutputStream:rawOutput]; | |
91 [output writeRawLittleEndian64:value]; | |
92 [output flush]; | |
93 | |
94 NSData* actual = | |
95 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
96 XCTAssertEqualObjects(data, actual); | |
97 | |
98 // Try different block sizes. | |
99 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { | |
100 rawOutput = [NSOutputStream outputStreamToMemory]; | |
101 output = [GPBCodedOutputStream streamWithOutputStream:rawOutput | |
102 bufferSize:blockSize]; | |
103 [output writeRawLittleEndian64:value]; | |
104 [output flush]; | |
105 | |
106 actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
107 XCTAssertEqualObjects(data, actual); | |
108 } | |
109 } | |
110 | |
111 - (void)assertWriteVarint:(NSData*)data value:(int64_t)value { | |
112 // Only do 32-bit write if the value fits in 32 bits. | |
113 if (GPBLogicalRightShift64(value, 32) == 0) { | |
114 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
115 GPBCodedOutputStream* output = | |
116 [GPBCodedOutputStream streamWithOutputStream:rawOutput]; | |
117 [output writeRawVarint32:(int32_t)value]; | |
118 [output flush]; | |
119 | |
120 NSData* actual = | |
121 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
122 XCTAssertEqualObjects(data, actual); | |
123 | |
124 // Also try computing size. | |
125 XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value), | |
126 (size_t)data.length); | |
127 } | |
128 | |
129 { | |
130 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
131 GPBCodedOutputStream* output = | |
132 [GPBCodedOutputStream streamWithOutputStream:rawOutput]; | |
133 [output writeRawVarint64:value]; | |
134 [output flush]; | |
135 | |
136 NSData* actual = | |
137 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
138 XCTAssertEqualObjects(data, actual); | |
139 | |
140 // Also try computing size. | |
141 XCTAssertEqual(GPBComputeRawVarint64Size(value), (size_t)data.length); | |
142 } | |
143 | |
144 // Try different block sizes. | |
145 for (int blockSize = 1; blockSize <= 16; blockSize *= 2) { | |
146 // Only do 32-bit write if the value fits in 32 bits. | |
147 if (GPBLogicalRightShift64(value, 32) == 0) { | |
148 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
149 GPBCodedOutputStream* output = | |
150 [GPBCodedOutputStream streamWithOutputStream:rawOutput | |
151 bufferSize:blockSize]; | |
152 | |
153 [output writeRawVarint32:(int32_t)value]; | |
154 [output flush]; | |
155 | |
156 NSData* actual = | |
157 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
158 XCTAssertEqualObjects(data, actual); | |
159 } | |
160 | |
161 { | |
162 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
163 GPBCodedOutputStream* output = | |
164 [GPBCodedOutputStream streamWithOutputStream:rawOutput | |
165 bufferSize:blockSize]; | |
166 | |
167 [output writeRawVarint64:value]; | |
168 [output flush]; | |
169 | |
170 NSData* actual = | |
171 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
172 XCTAssertEqualObjects(data, actual); | |
173 } | |
174 } | |
175 } | |
176 | |
177 - (void)testWriteVarint1 { | |
178 [self assertWriteVarint:bytes(0x00) value:0]; | |
179 } | |
180 | |
181 - (void)testWriteVarint2 { | |
182 [self assertWriteVarint:bytes(0x01) value:1]; | |
183 } | |
184 | |
185 - (void)testWriteVarint3 { | |
186 [self assertWriteVarint:bytes(0x7f) value:127]; | |
187 } | |
188 | |
189 - (void)testWriteVarint4 { | |
190 // 14882 | |
191 [self assertWriteVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)]; | |
192 } | |
193 | |
194 - (void)testWriteVarint5 { | |
195 // 2961488830 | |
196 [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b) | |
197 value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | | |
198 (0x04 << 21) | (0x0bLL << 28)]; | |
199 } | |
200 | |
201 - (void)testWriteVarint6 { | |
202 // 64-bit | |
203 // 7256456126 | |
204 [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b) | |
205 value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | | |
206 (0x04 << 21) | (0x1bLL << 28)]; | |
207 } | |
208 | |
209 - (void)testWriteVarint7 { | |
210 // 41256202580718336 | |
211 [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49) | |
212 value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | | |
213 (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) | | |
214 (0x24LL << 42) | (0x49LL << 49)]; | |
215 } | |
216 | |
217 - (void)testWriteVarint8 { | |
218 // 11964378330978735131 | |
219 [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, | |
220 0xa6, 0x01) | |
221 value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | | |
222 (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) | | |
223 (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) | | |
224 (0x01LL << 63)]; | |
225 } | |
226 | |
227 - (void)testWriteLittleEndian { | |
228 [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12) | |
229 value:0x12345678]; | |
230 [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a) | |
231 value:0x9abcdef0]; | |
232 | |
233 [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, | |
234 0x34, 0x12) | |
235 value:0x123456789abcdef0LL]; | |
236 [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, | |
237 0xbc, 0x9a) | |
238 value:0x9abcdef012345678LL]; | |
239 } | |
240 | |
241 - (void)testEncodeZigZag { | |
242 XCTAssertEqual(0U, GPBEncodeZigZag32(0)); | |
243 XCTAssertEqual(1U, GPBEncodeZigZag32(-1)); | |
244 XCTAssertEqual(2U, GPBEncodeZigZag32(1)); | |
245 XCTAssertEqual(3U, GPBEncodeZigZag32(-2)); | |
246 XCTAssertEqual(0x7FFFFFFEU, GPBEncodeZigZag32(0x3FFFFFFF)); | |
247 XCTAssertEqual(0x7FFFFFFFU, GPBEncodeZigZag32(0xC0000000)); | |
248 XCTAssertEqual(0xFFFFFFFEU, GPBEncodeZigZag32(0x7FFFFFFF)); | |
249 XCTAssertEqual(0xFFFFFFFFU, GPBEncodeZigZag32(0x80000000)); | |
250 | |
251 XCTAssertEqual(0ULL, GPBEncodeZigZag64(0)); | |
252 XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1)); | |
253 XCTAssertEqual(2ULL, GPBEncodeZigZag64(1)); | |
254 XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2)); | |
255 XCTAssertEqual(0x000000007FFFFFFEULL, | |
256 GPBEncodeZigZag64(0x000000003FFFFFFFLL)); | |
257 XCTAssertEqual(0x000000007FFFFFFFULL, | |
258 GPBEncodeZigZag64(0xFFFFFFFFC0000000LL)); | |
259 XCTAssertEqual(0x00000000FFFFFFFEULL, | |
260 GPBEncodeZigZag64(0x000000007FFFFFFFLL)); | |
261 XCTAssertEqual(0x00000000FFFFFFFFULL, | |
262 GPBEncodeZigZag64(0xFFFFFFFF80000000LL)); | |
263 XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL, | |
264 GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL)); | |
265 XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL, | |
266 GPBEncodeZigZag64(0x8000000000000000LL)); | |
267 | |
268 // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1) | |
269 // were chosen semi-randomly via keyboard bashing. | |
270 XCTAssertEqual(0U, GPBEncodeZigZag32(GPBDecodeZigZag32(0))); | |
271 XCTAssertEqual(1U, GPBEncodeZigZag32(GPBDecodeZigZag32(1))); | |
272 XCTAssertEqual(-1U, GPBEncodeZigZag32(GPBDecodeZigZag32(-1))); | |
273 XCTAssertEqual(14927U, GPBEncodeZigZag32(GPBDecodeZigZag32(14927))); | |
274 XCTAssertEqual(-3612U, GPBEncodeZigZag32(GPBDecodeZigZag32(-3612))); | |
275 | |
276 XCTAssertEqual(0ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(0))); | |
277 XCTAssertEqual(1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(1))); | |
278 XCTAssertEqual(-1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-1))); | |
279 XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927))); | |
280 XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612))); | |
281 | |
282 XCTAssertEqual(856912304801416ULL, | |
283 GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL))); | |
284 XCTAssertEqual(-75123905439571256ULL, | |
285 GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL))); | |
286 } | |
287 | |
288 - (void)testWriteWholeMessage { | |
289 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file | |
290 // that was generated with 2. | |
291 TestAllTypes* message = [self allSetRepeatedCount:2]; | |
292 | |
293 NSData* rawBytes = message.data; | |
294 NSData* goldenData = | |
295 [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes]; | |
296 XCTAssertEqualObjects(rawBytes, goldenData); | |
297 | |
298 // Try different block sizes. | |
299 for (int blockSize = 1; blockSize < 256; blockSize *= 2) { | |
300 NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory]; | |
301 GPBCodedOutputStream* output = | |
302 [GPBCodedOutputStream streamWithOutputStream:rawOutput | |
303 bufferSize:blockSize]; | |
304 [message writeToCodedOutputStream:output]; | |
305 [output flush]; | |
306 | |
307 NSData* actual = | |
308 [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; | |
309 XCTAssertEqualObjects(rawBytes, actual); | |
310 } | |
311 | |
312 // Not kGPBDefaultRepeatCount because we are comparing to a golden master file | |
313 // that was generated with 2. | |
314 TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2]; | |
315 rawBytes = extensions.data; | |
316 goldenData = [self getDataFileNamed:@"golden_packed_fields_message" | |
317 dataToWrite:rawBytes]; | |
318 XCTAssertEqualObjects(rawBytes, goldenData); | |
319 } | |
320 | |
321 @end | |
OLD | NEW |