OLD | NEW |
1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
4 // | 4 // |
5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
7 // met: | 7 // met: |
8 // | 8 // |
9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
(...skipping 26 matching lines...) Expand all Loading... |
37 * both a double and a signed 64-bit integer. | 37 * both a double and a signed 64-bit integer. |
38 * | 38 * |
39 * Test suite is written using Jasmine -- see http://jasmine.github.io/ | 39 * Test suite is written using Jasmine -- see http://jasmine.github.io/ |
40 * | 40 * |
41 * @author aappleby@google.com (Austin Appleby) | 41 * @author aappleby@google.com (Austin Appleby) |
42 */ | 42 */ |
43 | 43 |
44 goog.require('goog.testing.asserts'); | 44 goog.require('goog.testing.asserts'); |
45 goog.require('jspb.BinaryConstants'); | 45 goog.require('jspb.BinaryConstants'); |
46 goog.require('jspb.BinaryDecoder'); | 46 goog.require('jspb.BinaryDecoder'); |
47 goog.require('jspb.BinaryWriter'); | 47 goog.require('jspb.BinaryEncoder'); |
48 | 48 |
49 | 49 |
50 /** | 50 /** |
51 * Tests raw encoding and decoding of unsigned types. | 51 * Tests encoding and decoding of unsigned types. |
52 * @param {Function} readValue | 52 * @param {Function} readValue |
53 * @param {Function} writeValue | 53 * @param {Function} writeValue |
54 * @param {number} epsilon | 54 * @param {number} epsilon |
55 * @param {number} upperLimit | 55 * @param {number} upperLimit |
56 * @param {Function} filter | 56 * @param {Function} filter |
57 * @suppress {missingProperties|visibility} | 57 * @suppress {missingProperties|visibility} |
58 */ | 58 */ |
59 function doTestUnsignedValue(readValue, | 59 function doTestUnsignedValue(readValue, |
60 writeValue, epsilon, upperLimit, filter) { | 60 writeValue, epsilon, upperLimit, filter) { |
61 var writer = new jspb.BinaryWriter(); | 61 var encoder = new jspb.BinaryEncoder(); |
62 | 62 |
63 // Encode zero and limits. | 63 // Encode zero and limits. |
64 writeValue.call(writer, filter(0)); | 64 writeValue.call(encoder, filter(0)); |
65 writeValue.call(writer, filter(epsilon)); | 65 writeValue.call(encoder, filter(epsilon)); |
66 writeValue.call(writer, filter(upperLimit)); | 66 writeValue.call(encoder, filter(upperLimit)); |
67 | 67 |
68 // Encode positive values. | 68 // Encode positive values. |
69 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { | 69 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { |
70 writeValue.call(writer, filter(cursor)); | 70 writeValue.call(encoder, filter(cursor)); |
71 } | 71 } |
72 | 72 |
73 var reader = jspb.BinaryDecoder.alloc(writer.getResultBuffer()); | 73 var decoder = jspb.BinaryDecoder.alloc(encoder.end()); |
74 | 74 |
75 // Check zero and limits. | 75 // Check zero and limits. |
76 assertEquals(filter(0), readValue.call(reader)); | 76 assertEquals(filter(0), readValue.call(decoder)); |
77 assertEquals(filter(epsilon), readValue.call(reader)); | 77 assertEquals(filter(epsilon), readValue.call(decoder)); |
78 assertEquals(filter(upperLimit), readValue.call(reader)); | 78 assertEquals(filter(upperLimit), readValue.call(decoder)); |
79 | 79 |
80 // Check positive values. | 80 // Check positive values. |
81 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { | 81 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { |
82 if (filter(cursor) != readValue.call(reader)) throw 'fail!'; | 82 if (filter(cursor) != readValue.call(decoder)) throw 'fail!'; |
83 } | 83 } |
| 84 |
| 85 // Encoding values outside the valid range should assert. |
| 86 assertThrows(function() {writeValue.call(encoder, -1);}); |
| 87 assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);}); |
84 } | 88 } |
85 | 89 |
86 | 90 |
87 /** | 91 /** |
88 * Tests raw encoding and decoding of signed types. | 92 * Tests encoding and decoding of signed types. |
89 * @param {Function} readValue | 93 * @param {Function} readValue |
90 * @param {Function} writeValue | 94 * @param {Function} writeValue |
91 * @param {number} epsilon | 95 * @param {number} epsilon |
92 * @param {number} lowerLimit | 96 * @param {number} lowerLimit |
93 * @param {number} upperLimit | 97 * @param {number} upperLimit |
94 * @param {Function} filter | 98 * @param {Function} filter |
95 * @suppress {missingProperties} | 99 * @suppress {missingProperties} |
96 */ | 100 */ |
97 function doTestSignedValue(readValue, | 101 function doTestSignedValue(readValue, |
98 writeValue, epsilon, lowerLimit, upperLimit, filter) { | 102 writeValue, epsilon, lowerLimit, upperLimit, filter) { |
99 var writer = new jspb.BinaryWriter(); | 103 var encoder = new jspb.BinaryEncoder(); |
100 | 104 |
101 // Encode zero and limits. | 105 // Encode zero and limits. |
102 writeValue.call(writer, filter(lowerLimit)); | 106 writeValue.call(encoder, filter(lowerLimit)); |
103 writeValue.call(writer, filter(-epsilon)); | 107 writeValue.call(encoder, filter(-epsilon)); |
104 writeValue.call(writer, filter(0)); | 108 writeValue.call(encoder, filter(0)); |
105 writeValue.call(writer, filter(epsilon)); | 109 writeValue.call(encoder, filter(epsilon)); |
106 writeValue.call(writer, filter(upperLimit)); | 110 writeValue.call(encoder, filter(upperLimit)); |
107 | 111 |
108 var inputValues = []; | 112 var inputValues = []; |
109 | 113 |
110 // Encode negative values. | 114 // Encode negative values. |
111 for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { | 115 for (var cursor = lowerLimit; cursor < -epsilon; cursor /= 1.1) { |
112 var val = filter(cursor); | 116 var val = filter(cursor); |
113 writeValue.call(writer, val); | 117 writeValue.call(encoder, val); |
114 inputValues.push(val); | 118 inputValues.push(val); |
115 } | 119 } |
116 | 120 |
117 // Encode positive values. | 121 // Encode positive values. |
118 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { | 122 for (var cursor = epsilon; cursor < upperLimit; cursor *= 1.1) { |
119 var val = filter(cursor); | 123 var val = filter(cursor); |
120 writeValue.call(writer, val); | 124 writeValue.call(encoder, val); |
121 inputValues.push(val); | 125 inputValues.push(val); |
122 } | 126 } |
123 | 127 |
124 var reader = jspb.BinaryDecoder.alloc(writer.getResultBuffer()); | 128 var decoder = jspb.BinaryDecoder.alloc(encoder.end()); |
125 | 129 |
126 // Check zero and limits. | 130 // Check zero and limits. |
127 assertEquals(filter(lowerLimit), readValue.call(reader)); | 131 assertEquals(filter(lowerLimit), readValue.call(decoder)); |
128 assertEquals(filter(-epsilon), readValue.call(reader)); | 132 assertEquals(filter(-epsilon), readValue.call(decoder)); |
129 assertEquals(filter(0), readValue.call(reader)); | 133 assertEquals(filter(0), readValue.call(decoder)); |
130 assertEquals(filter(epsilon), readValue.call(reader)); | 134 assertEquals(filter(epsilon), readValue.call(decoder)); |
131 assertEquals(filter(upperLimit), readValue.call(reader)); | 135 assertEquals(filter(upperLimit), readValue.call(decoder)); |
132 | 136 |
133 // Verify decoded values. | 137 // Verify decoded values. |
134 for (var i = 0; i < inputValues.length; i++) { | 138 for (var i = 0; i < inputValues.length; i++) { |
135 assertEquals(inputValues[i], readValue.call(reader)); | 139 assertEquals(inputValues[i], readValue.call(decoder)); |
136 } | 140 } |
| 141 |
| 142 // Encoding values outside the valid range should assert. |
| 143 assertThrows(function() {writeValue.call(encoder, lowerLimit * 1.1);}); |
| 144 assertThrows(function() {writeValue.call(encoder, upperLimit * 1.1);}); |
137 } | 145 } |
138 | 146 |
139 describe('binaryDecoderTest', function() { | 147 describe('binaryDecoderTest', function() { |
140 /** | 148 /** |
141 * Tests the decoder instance cache. | 149 * Tests the decoder instance cache. |
142 * @suppress {visibility} | 150 * @suppress {visibility} |
143 */ | 151 */ |
144 it('testInstanceCache', function() { | 152 it('testInstanceCache', function() { |
145 // Empty the instance caches. | 153 // Empty the instance caches. |
146 jspb.BinaryDecoder.instanceCache_ = []; | 154 jspb.BinaryDecoder.instanceCache_ = []; |
(...skipping 15 matching lines...) Expand all Loading... |
162 decoder3.free(); | 170 decoder3.free(); |
163 | 171 |
164 assertEquals(3, jspb.BinaryDecoder.instanceCache_.length); | 172 assertEquals(3, jspb.BinaryDecoder.instanceCache_.length); |
165 }); | 173 }); |
166 | 174 |
167 | 175 |
168 /** | 176 /** |
169 * Tests reading 64-bit integers as hash strings. | 177 * Tests reading 64-bit integers as hash strings. |
170 */ | 178 */ |
171 it('testHashStrings', function() { | 179 it('testHashStrings', function() { |
172 var writer = new jspb.BinaryWriter(); | 180 var encoder = new jspb.BinaryEncoder(); |
173 | 181 |
174 var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00, | 182 var hashA = String.fromCharCode(0x00, 0x00, 0x00, 0x00, |
175 0x00, 0x00, 0x00, 0x00); | 183 0x00, 0x00, 0x00, 0x00); |
176 var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00, | 184 var hashB = String.fromCharCode(0x12, 0x34, 0x00, 0x00, |
177 0x00, 0x00, 0x00, 0x00); | 185 0x00, 0x00, 0x00, 0x00); |
178 var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78, | 186 var hashC = String.fromCharCode(0x12, 0x34, 0x56, 0x78, |
179 0x87, 0x65, 0x43, 0x21); | 187 0x87, 0x65, 0x43, 0x21); |
180 var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, | 188 var hashD = String.fromCharCode(0xFF, 0xFF, 0xFF, 0xFF, |
181 0xFF, 0xFF, 0xFF, 0xFF); | 189 0xFF, 0xFF, 0xFF, 0xFF); |
182 | 190 |
183 writer.rawWriteVarintHash64(hashA); | 191 encoder.writeVarintHash64(hashA); |
184 writer.rawWriteVarintHash64(hashB); | 192 encoder.writeVarintHash64(hashB); |
185 writer.rawWriteVarintHash64(hashC); | 193 encoder.writeVarintHash64(hashC); |
186 writer.rawWriteVarintHash64(hashD); | 194 encoder.writeVarintHash64(hashD); |
187 | 195 |
188 writer.rawWriteFixedHash64(hashA); | 196 encoder.writeFixedHash64(hashA); |
189 writer.rawWriteFixedHash64(hashB); | 197 encoder.writeFixedHash64(hashB); |
190 writer.rawWriteFixedHash64(hashC); | 198 encoder.writeFixedHash64(hashC); |
191 writer.rawWriteFixedHash64(hashD); | 199 encoder.writeFixedHash64(hashD); |
192 | 200 |
193 var decoder = jspb.BinaryDecoder.alloc(writer.getResultBuffer()); | 201 var decoder = jspb.BinaryDecoder.alloc(encoder.end()); |
194 | 202 |
195 assertEquals(hashA, decoder.readVarintHash64()); | 203 assertEquals(hashA, decoder.readVarintHash64()); |
196 assertEquals(hashB, decoder.readVarintHash64()); | 204 assertEquals(hashB, decoder.readVarintHash64()); |
197 assertEquals(hashC, decoder.readVarintHash64()); | 205 assertEquals(hashC, decoder.readVarintHash64()); |
198 assertEquals(hashD, decoder.readVarintHash64()); | 206 assertEquals(hashD, decoder.readVarintHash64()); |
199 | 207 |
200 assertEquals(hashA, decoder.readFixedHash64()); | 208 assertEquals(hashA, decoder.readFixedHash64()); |
201 assertEquals(hashB, decoder.readFixedHash64()); | 209 assertEquals(hashB, decoder.readFixedHash64()); |
202 assertEquals(hashC, decoder.readFixedHash64()); | 210 assertEquals(hashC, decoder.readFixedHash64()); |
203 assertEquals(hashD, decoder.readFixedHash64()); | 211 assertEquals(hashD, decoder.readFixedHash64()); |
204 }); | 212 }); |
205 | 213 |
206 | 214 |
207 /** | 215 /** |
208 * Verifies that misuse of the decoder class triggers assertions. | 216 * Verifies that misuse of the decoder class triggers assertions. |
209 * @suppress {checkTypes|visibility} | 217 * @suppress {checkTypes|visibility} |
210 */ | 218 */ |
211 it('testDecodeErrors', function() { | 219 it('testDecodeErrors', function() { |
212 // Reading a value past the end of the stream should trigger an assertion. | 220 // Reading a value past the end of the stream should trigger an assertion. |
213 var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]); | 221 var decoder = jspb.BinaryDecoder.alloc([0, 1, 2]); |
214 assertThrows(function() {decoder.readUint64()}); | 222 assertThrows(function() {decoder.readUint64()}); |
215 | 223 |
216 // Overlong varints should trigger assertions. | 224 // Overlong varints should trigger assertions. |
217 decoder.setBlock( | 225 decoder.setBlock([255, 255, 255, 255, 255, 255, |
218 [255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); | 226 255, 255, 255, 255, 255, 0]); |
219 assertThrows(function() {decoder.readUnsignedVarint64()}); | 227 assertThrows(function() {decoder.readUnsignedVarint64()}); |
220 decoder.reset(); | 228 decoder.reset(); |
221 assertThrows(function() {decoder.readSignedVarint64()}); | 229 assertThrows(function() {decoder.readSignedVarint64()}); |
222 decoder.reset(); | 230 decoder.reset(); |
223 assertThrows(function() {decoder.readZigzagVarint64()}); | 231 assertThrows(function() {decoder.readZigzagVarint64()}); |
224 | 232 |
225 // Positive 32-bit varints encoded with 1 bits in positions 33 through 35 | 233 // Positive 32-bit varints encoded with 1 bits in positions 33 through 35 |
226 // should trigger assertions. | 234 // should trigger assertions. |
227 decoder.setBlock([255, 255, 255, 255, 0x1F]); | 235 decoder.setBlock([255, 255, 255, 255, 0x1F]); |
228 assertThrows(function() {decoder.readUnsignedVarint32()}); | 236 assertThrows(function() {decoder.readUnsignedVarint32()}); |
229 | 237 |
230 decoder.setBlock([255, 255, 255, 255, 0x2F]); | 238 decoder.setBlock([255, 255, 255, 255, 0x2F]); |
231 assertThrows(function() {decoder.readUnsignedVarint32()}); | 239 assertThrows(function() {decoder.readUnsignedVarint32()}); |
232 | 240 |
233 decoder.setBlock([255, 255, 255, 255, 0x4F]); | 241 decoder.setBlock([255, 255, 255, 255, 0x4F]); |
234 assertThrows(function() {decoder.readUnsignedVarint32()}); | 242 assertThrows(function() {decoder.readUnsignedVarint32()}); |
235 | 243 |
236 // Negative 32-bit varints encoded with non-1 bits in the high dword should | 244 // Negative 32-bit varints encoded with non-1 bits in the high dword should |
237 // trigger assertions. | 245 // trigger assertions. |
238 decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]); | 246 decoder.setBlock([255, 255, 255, 255, 255, 255, 0, 255, 255, 1]); |
239 assertThrows(function() {decoder.readUnsignedVarint32()}); | 247 assertThrows(function() {decoder.readUnsignedVarint32()}); |
240 | 248 |
241 decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); | 249 decoder.setBlock([255, 255, 255, 255, 255, 255, 255, 255, 255, 0]); |
242 assertThrows(function() {decoder.readUnsignedVarint32()}); | 250 assertThrows(function() {decoder.readUnsignedVarint32()}); |
243 }); | 251 }); |
244 | 252 |
245 | 253 |
246 /** | 254 /** |
247 * Tests raw encoding and decoding of unsigned integers. | 255 * Tests encoding and decoding of unsigned integers. |
248 */ | 256 */ |
249 it('testRawUnsigned', function() { | 257 it('testUnsignedIntegers', function() { |
250 doTestUnsignedValue( | 258 doTestUnsignedValue( |
251 jspb.BinaryDecoder.prototype.readUint8, | 259 jspb.BinaryDecoder.prototype.readUint8, |
252 jspb.BinaryWriter.prototype.rawWriteUint8, | 260 jspb.BinaryEncoder.prototype.writeUint8, |
253 1, 0xFF, Math.round); | 261 1, 0xFF, Math.round); |
254 | 262 |
255 doTestUnsignedValue( | 263 doTestUnsignedValue( |
256 jspb.BinaryDecoder.prototype.readUint16, | 264 jspb.BinaryDecoder.prototype.readUint16, |
257 jspb.BinaryWriter.prototype.rawWriteUint16, | 265 jspb.BinaryEncoder.prototype.writeUint16, |
258 1, 0xFFFF, Math.round); | 266 1, 0xFFFF, Math.round); |
259 | 267 |
260 doTestUnsignedValue( | 268 doTestUnsignedValue( |
261 jspb.BinaryDecoder.prototype.readUint32, | 269 jspb.BinaryDecoder.prototype.readUint32, |
262 jspb.BinaryWriter.prototype.rawWriteUint32, | 270 jspb.BinaryEncoder.prototype.writeUint32, |
263 1, 0xFFFFFFFF, Math.round); | 271 1, 0xFFFFFFFF, Math.round); |
264 | 272 |
265 doTestUnsignedValue( | 273 doTestUnsignedValue( |
266 jspb.BinaryDecoder.prototype.readUint64, | 274 jspb.BinaryDecoder.prototype.readUint64, |
267 jspb.BinaryWriter.prototype.rawWriteUint64, | 275 jspb.BinaryEncoder.prototype.writeUint64, |
268 1, Math.pow(2, 64) - 1025, Math.round); | 276 1, Math.pow(2, 64) - 1025, Math.round); |
269 }); | 277 }); |
270 | 278 |
271 | 279 |
272 /** | 280 /** |
273 * Tests raw encoding and decoding of signed integers. | 281 * Tests encoding and decoding of signed integers. |
274 */ | 282 */ |
275 it('testRawSigned', function() { | 283 it('testSignedIntegers', function() { |
276 doTestSignedValue( | 284 doTestSignedValue( |
277 jspb.BinaryDecoder.prototype.readInt8, | 285 jspb.BinaryDecoder.prototype.readInt8, |
278 jspb.BinaryWriter.prototype.rawWriteInt8, | 286 jspb.BinaryEncoder.prototype.writeInt8, |
279 1, -0x80, 0x7F, Math.round); | 287 1, -0x80, 0x7F, Math.round); |
280 | 288 |
281 doTestSignedValue( | 289 doTestSignedValue( |
282 jspb.BinaryDecoder.prototype.readInt16, | 290 jspb.BinaryDecoder.prototype.readInt16, |
283 jspb.BinaryWriter.prototype.rawWriteInt16, | 291 jspb.BinaryEncoder.prototype.writeInt16, |
284 1, -0x8000, 0x7FFF, Math.round); | 292 1, -0x8000, 0x7FFF, Math.round); |
285 | 293 |
286 doTestSignedValue( | 294 doTestSignedValue( |
287 jspb.BinaryDecoder.prototype.readInt32, | 295 jspb.BinaryDecoder.prototype.readInt32, |
288 jspb.BinaryWriter.prototype.rawWriteInt32, | 296 jspb.BinaryEncoder.prototype.writeInt32, |
289 1, -0x80000000, 0x7FFFFFFF, Math.round); | 297 1, -0x80000000, 0x7FFFFFFF, Math.round); |
290 | 298 |
291 doTestSignedValue( | 299 doTestSignedValue( |
292 jspb.BinaryDecoder.prototype.readInt64, | 300 jspb.BinaryDecoder.prototype.readInt64, |
293 jspb.BinaryWriter.prototype.rawWriteInt64, | 301 jspb.BinaryEncoder.prototype.writeInt64, |
294 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); | 302 1, -Math.pow(2, 63), Math.pow(2, 63) - 513, Math.round); |
295 }); | 303 }); |
296 | 304 |
297 | 305 |
298 /** | 306 /** |
299 * Tests raw encoding and decoding of floats. | 307 * Tests encoding and decoding of floats. |
300 */ | 308 */ |
301 it('testRawFloats', function() { | 309 it('testFloats', function() { |
302 /** | 310 /** |
303 * @param {number} x | 311 * @param {number} x |
304 * @return {number} | 312 * @return {number} |
305 */ | 313 */ |
306 function truncate(x) { | 314 function truncate(x) { |
307 var temp = new Float32Array(1); | 315 var temp = new Float32Array(1); |
308 temp[0] = x; | 316 temp[0] = x; |
309 return temp[0]; | 317 return temp[0]; |
310 } | 318 } |
311 doTestSignedValue( | 319 doTestSignedValue( |
312 jspb.BinaryDecoder.prototype.readFloat, | 320 jspb.BinaryDecoder.prototype.readFloat, |
313 jspb.BinaryWriter.prototype.rawWriteFloat, | 321 jspb.BinaryEncoder.prototype.writeFloat, |
314 jspb.BinaryConstants.FLOAT32_EPS, | 322 jspb.BinaryConstants.FLOAT32_EPS, |
315 -jspb.BinaryConstants.FLOAT32_MAX, | 323 -jspb.BinaryConstants.FLOAT32_MAX, |
316 jspb.BinaryConstants.FLOAT32_MAX, | 324 jspb.BinaryConstants.FLOAT32_MAX, |
317 truncate); | 325 truncate); |
318 | 326 |
319 doTestSignedValue( | 327 doTestSignedValue( |
320 jspb.BinaryDecoder.prototype.readDouble, | 328 jspb.BinaryDecoder.prototype.readDouble, |
321 jspb.BinaryWriter.prototype.rawWriteDouble, | 329 jspb.BinaryEncoder.prototype.writeDouble, |
322 jspb.BinaryConstants.FLOAT64_EPS * 10, | 330 jspb.BinaryConstants.FLOAT64_EPS * 10, |
323 -jspb.BinaryConstants.FLOAT64_MAX, | 331 -jspb.BinaryConstants.FLOAT64_MAX, |
324 jspb.BinaryConstants.FLOAT64_MAX, | 332 jspb.BinaryConstants.FLOAT64_MAX, |
325 function(x) { return x; }); | 333 function(x) { return x; }); |
326 }); | 334 }); |
327 }); | 335 }); |
OLD | NEW |