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