Austin Schuh | 272c613 | 2020-11-14 16:37:52 -0800 | [diff] [blame^] | 1 | // Run this using JavaScriptTest.sh |
| 2 | var assert = require('assert'); |
| 3 | var fs = require('fs'); |
| 4 | |
| 5 | var flexbuffers = require('../js/flexbuffers').flexbuffers; |
| 6 | global.flexbuffers = flexbuffers; |
| 7 | |
| 8 | function main() { |
| 9 | testSingleValueBuffers(); |
| 10 | testGoldBuffer(); |
| 11 | testEncode(); |
| 12 | testIndirectAdd(); |
| 13 | testIndirectWithCache(); |
| 14 | testMapBuilder(); |
| 15 | testRoundTrip(); |
| 16 | testRoundTripWithBuilder(); |
| 17 | testDeduplicationOff(); |
| 18 | testBugWhereOffestWereStoredAsIntInsteadOfUInt(); |
| 19 | } |
| 20 | |
| 21 | function testSingleValueBuffers() { |
| 22 | { // null |
| 23 | const ref = flexbuffers.toReference(new Uint8Array([0, 0, 1]).buffer); |
| 24 | assert.strictEqual(true, ref.isNull()); |
| 25 | } |
| 26 | |
| 27 | function _assert(object, buffer) { |
| 28 | assert.deepStrictEqual(flexbuffers.toObject(new Uint8Array(buffer).buffer), object); |
| 29 | } |
| 30 | _assert(true, [1, 104, 1]); |
| 31 | _assert(false, [0, 104, 1]); |
| 32 | _assert(25, [25, 4, 1]); |
| 33 | _assert(-25, [231, 4, 1]); |
| 34 | _assert(230, [230, 8, 1]); |
| 35 | _assert(230, [230, 0, 5, 2]); |
| 36 | _assert(-1025, [255, 251, 5, 2]); |
| 37 | _assert(1025, [1, 4, 9, 2]); |
| 38 | _assert(2147483647, [255, 255, 255, 127, 6, 4]); |
| 39 | _assert(-2147483648, [0, 0, 0, 128, 6, 4]); |
| 40 | _assert(4294967295n, [255, 255, 255, 255, 0, 0, 0, 0, 7, 8]); |
| 41 | _assert(9223372036854775807n, [255, 255, 255, 255, 255, 255, 255, 127, 7, 8]); |
| 42 | _assert(-9223372036854775808n, [0, 0, 0, 0, 0, 0, 0, 128, 7, 8]); |
| 43 | _assert(18446744073709551615n, [255, 255, 255, 255, 255, 255, 255, 255, 11, 8]); |
| 44 | _assert(4.5, [0, 0, 144, 64, 14, 4]); |
| 45 | _assert(0.10000000149011612, [205, 204, 204, 61, 14, 4]); |
| 46 | _assert(0.1, [154, 153, 153, 153, 153, 153, 185, 63, 15, 8]); |
| 47 | _assert(-1025, [255, 251, 5, 2]); |
| 48 | _assert("Maxim", [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]); |
| 49 | _assert("hello 😱", [10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]); |
| 50 | _assert({a:12}, [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]); |
| 51 | _assert({"":45, "a": 12}, [0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]); |
| 52 | } |
| 53 | |
| 54 | function testEncode() { |
| 55 | function _assert(value, buffer) { |
| 56 | assert.deepStrictEqual(flexbuffers.encode(value), new Uint8Array(buffer)); |
| 57 | } |
| 58 | _assert(null, [0, 0, 1]); |
| 59 | _assert(true, [1, 104, 1]); |
| 60 | _assert(false, [0, 104, 1]); |
| 61 | _assert(1, [1, 4, 1]); |
| 62 | _assert(230, [230, 0, 5, 2]); |
| 63 | _assert(1025, [1, 4, 5, 2]); |
| 64 | _assert(-1025, [255, 251, 5, 2]); |
| 65 | _assert(0x100000001, [1, 0, 0, 0, 1, 0, 0, 0, 7, 8]); |
| 66 | _assert(0.1, [154, 153, 153, 153, 153, 153, 185, 63, 15, 8]); |
| 67 | _assert(0.5, [0, 0, 0, 63, 14, 4]); |
| 68 | _assert(new Uint8Array([1, 2, 3]), [3, 1, 2, 3, 3, 100, 1]); |
| 69 | _assert("Maxim", [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]); |
| 70 | _assert("hello 😱", [10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]); |
| 71 | _assert([1, 2], [1, 2, 2, 64, 1]); |
| 72 | _assert([-1, 256], [255, 255, 0, 1, 4, 65, 1]); |
| 73 | _assert([-45, 256000], [211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1]); |
| 74 | _assert([1.1, -256.0], [2, 0, 0, 0, 0, 0, 0, 0, 154, 153, 153, 153, 153, 153, 241, 63, 0, 255, 255, 255, 255, 255, 255, 255, 15, 5, 18, 43, 1]); |
| 75 | _assert([1, 2, 4], [1, 2, 4, 3, 76, 1]); |
| 76 | _assert([-1, 256, 4], [255, 255, 0, 1, 4, 0, 6, 77, 1]); |
| 77 | _assert([[61], 64], [1, 61, 2, 2, 64, 44, 4, 4, 40, 1]); |
| 78 | _assert(["foo", "bar", "baz"], [3, 102, 111, 111, 0, 3, 98, 97, 114, 0, 3, 98, 97, 122, 0, 3, 15, 11, 7, 3, 60, 1]); |
| 79 | _assert(["foo", "bar", "baz", "foo", "bar", "baz"], [3, 102, 111, 111, 0, 3, 98, 97, 114, 0, 3, 98, 97, 122, 0, 6, 15, 11, 7, 18, 14, 10, 6, 60, 1]); |
| 80 | _assert([true, false, true], [3, 1, 0, 1, 3, 144, 1]); |
| 81 | _assert(['foo', 1, -5, 1.3, true], [ |
| 82 | 3, 102, 111, 111, 0, 0, 0, 0, |
| 83 | 5, 0, 0, 0, 0, 0, 0, 0, |
| 84 | 15, 0, 0, 0, 0, 0, 0, 0, |
| 85 | 1, 0, 0, 0, 0, 0, 0, 0, |
| 86 | 251, 255, 255, 255, 255, 255, 255, 255, |
| 87 | 205, 204, 204, 204, 204, 204, 244, 63, |
| 88 | 1, 0, 0, 0, 0, 0, 0, 0, |
| 89 | 20, 4, 4, 15, 104, 45, 43, 1 |
| 90 | ]); |
| 91 | _assert([1, 3.3, 'max', true, null, false], [ |
| 92 | 3, 109, 97, 120, 0, 0, 0, 0, |
| 93 | 6, 0, 0, 0, 0, 0, 0, 0, |
| 94 | 1, 0, 0, 0, 0, 0, 0, 0, |
| 95 | 102, 102, 102, 102, 102, 102, 10, 64, |
| 96 | 31, 0, 0, 0, 0, 0, 0, 0, |
| 97 | 1, 0, 0, 0, 0, 0, 0, 0, |
| 98 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 99 | 0, 0, 0, 0, 0, 0, 0, 0, |
| 100 | 4, 15, 20, 104, 0, 104, 54, 43, 1 |
| 101 | ]); |
| 102 | _assert({"a": 12}, [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]); |
| 103 | _assert({"a": 12, "":45}, [0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]); |
| 104 | // JS currently does not support key vector offset sharing |
| 105 | _assert([{'something':12}, {'something': 45}], [ |
| 106 | 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, |
| 107 | 1, 11, 1, 1, 1, 12, 4, 6, 1, 1, 45, 4, 2, 8, 4, 36, 36, 4, 40, 1 |
| 108 | ]); |
| 109 | } |
| 110 | |
| 111 | function testDeduplicationOff() { |
| 112 | let buffer = flexbuffers.encode([{'something':12}, {'something': 45}], 1, true, true, false); |
| 113 | assert.deepStrictEqual(buffer, new Uint8Array([ |
| 114 | 115, 111, 109, 101, 116, 104, 105, 110, 103, |
| 115 | 0, 1, 11, 1, 1, 1, 12, 4, 1, |
| 116 | 18, 1, 1, 1, 45, 4, 2, 10, 4, |
| 117 | 36, 36, 4, 40, 1 |
| 118 | ])); |
| 119 | |
| 120 | buffer = flexbuffers.encode([{'something':12}, {'something': 45}], 1, true, false, false); |
| 121 | assert.deepStrictEqual(buffer, new Uint8Array([ |
| 122 | 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, |
| 123 | 1, 11, 1, 1, 1, 12, 4, 115, 111, 109, |
| 124 | 101, 116, 104, 105, 110, 103, 0, 1, 11, 1, |
| 125 | 1, 1, 45, 4, 2, 20, 4, 36, 36, 4, |
| 126 | 40, 1 |
| 127 | ])); |
| 128 | |
| 129 | buffer = flexbuffers.encode(['something', 'something', 'dark'], 1, true, false, false); |
| 130 | assert.deepStrictEqual(buffer, new Uint8Array([ |
| 131 | 9, 115, 111, 109, 101, 116, 104, |
| 132 | 105, 110, 103, 0, 4, 100, 97, |
| 133 | 114, 107, 0, 3, 17, 18, 8, |
| 134 | 3, 60, 1 |
| 135 | ])); |
| 136 | |
| 137 | buffer = flexbuffers.encode(['something', 'something', 'dark'], 1, false, false, false); |
| 138 | assert.deepStrictEqual(buffer, new Uint8Array([ |
| 139 | 9, 115, 111, 109, 101, 116, 104, 105, 110, |
| 140 | 103, 0, 9, 115, 111, 109, 101, 116, 104, |
| 141 | 105, 110, 103, 0, 4, 100, 97, 114, 107, |
| 142 | 0, 3, 28, 18, 8, 3, 60, 1 |
| 143 | ])); |
| 144 | } |
| 145 | |
| 146 | function testIndirectAdd() { |
| 147 | function _assertInt(buffer, value, indirect = false, cache = false) { |
| 148 | const builder = flexbuffers.builder(); |
| 149 | builder.addInt(value, indirect, cache); |
| 150 | const data = builder.finish(); |
| 151 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 152 | } |
| 153 | function _assertUInt(buffer, value, indirect = false, cache = false) { |
| 154 | const builder = flexbuffers.builder(); |
| 155 | builder.addUInt(value, indirect, cache); |
| 156 | const data = builder.finish(); |
| 157 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 158 | } |
| 159 | function _assertFloat(buffer, value, indirect = false, cache = false) { |
| 160 | const builder = flexbuffers.builder(); |
| 161 | builder.addFloat(value, indirect, cache); |
| 162 | const data = builder.finish(); |
| 163 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 164 | } |
| 165 | _assertInt([0, 4, 1], 0); |
| 166 | _assertInt([0, 1, 24, 1], 0, true); |
| 167 | _assertInt([255, 0, 5, 2], 255); |
| 168 | |
| 169 | _assertUInt([0, 8, 1], 0); |
| 170 | _assertUInt([0, 1, 28, 1], 0, true); |
| 171 | _assertUInt([255, 8, 1], 255); |
| 172 | |
| 173 | _assertUInt([185, 115, 175, 118, 250, 84, 8, 0, 11, 8], 2345234523452345); |
| 174 | _assertUInt([185, 115, 175, 118, 250, 84, 8, 0, 8, 31, 1], 2345234523452345, true); |
| 175 | _assertInt([185, 115, 175, 118, 250, 84, 8, 0, 7, 8], 2345234523452345); |
| 176 | _assertInt([185, 115, 175, 118, 250, 84, 8, 0, 8, 27, 1], 2345234523452345, true); |
| 177 | |
| 178 | _assertFloat([154, 153, 153, 153, 153, 153, 185, 63, 15, 8], 0.1); |
| 179 | _assertFloat([154, 153, 153, 153, 153, 153, 185, 63, 8, 35, 1], 0.1, true); |
| 180 | _assertFloat([0, 0, 0, 0, 14, 4], 0); |
| 181 | _assertFloat([0, 0, 0, 0, 4, 34, 1], 0, true); |
| 182 | } |
| 183 | |
| 184 | function testIndirectWithCache() { |
| 185 | function _assertInt(buffer, values) { |
| 186 | const builder = flexbuffers.builder(); |
| 187 | builder.startVector(); |
| 188 | values.forEach(v => { |
| 189 | builder.addInt(v, true, true) |
| 190 | }); |
| 191 | builder.end(); |
| 192 | const data = builder.finish(); |
| 193 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 194 | } |
| 195 | |
| 196 | function _assertUInt(buffer, values) { |
| 197 | const builder = flexbuffers.builder(); |
| 198 | builder.startVector(); |
| 199 | values.forEach(v => { |
| 200 | builder.addUInt(v, true, true); |
| 201 | }); |
| 202 | builder.end(); |
| 203 | const data = builder.finish(); |
| 204 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 205 | } |
| 206 | |
| 207 | function _assertFloat(buffer, values) { |
| 208 | const builder = flexbuffers.builder(); |
| 209 | builder.startVector(); |
| 210 | values.forEach(v => { |
| 211 | builder.addFloat(v, true, true); |
| 212 | }); |
| 213 | builder.end(); |
| 214 | const data = builder.finish(); |
| 215 | assert.deepStrictEqual(data, new Uint8Array(buffer)); |
| 216 | } |
| 217 | |
| 218 | _assertInt( |
| 219 | [185, 115, 175, 118, 250, 84, 8, 0, 4, 9, 10, 11, 12, 27, 27, 27, 27, 8, 40, 1], |
| 220 | [2345234523452345, 2345234523452345, 2345234523452345, 2345234523452345] |
| 221 | ); |
| 222 | |
| 223 | _assertUInt( |
| 224 | [185, 115, 175, 118, 250, 84, 8, 0, 4, 9, 10, 11, 12, 31, 31, 31, 31, 8, 40, 1], |
| 225 | [2345234523452345, 2345234523452345, 2345234523452345, 2345234523452345] |
| 226 | ); |
| 227 | |
| 228 | _assertFloat( |
| 229 | [154, 153, 153, 153, 153, 153, 185, 63, 4, 9, 10, 11, 12, 35, 35, 35, 35, 8, 40, 1], |
| 230 | [0.1, 0.1, 0.1, 0.1] |
| 231 | ); |
| 232 | } |
| 233 | |
| 234 | function testMapBuilder() { |
| 235 | const builder = flexbuffers.builder(); |
| 236 | builder.startMap(); |
| 237 | builder.addKey('a'); |
| 238 | builder.add(12); |
| 239 | builder.addKey(''); |
| 240 | builder.add(45); |
| 241 | builder.end(); |
| 242 | const data = builder.finish(); |
| 243 | assert.deepStrictEqual(data, new Uint8Array([97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1])); |
| 244 | } |
| 245 | |
| 246 | function testRoundTrip() { |
| 247 | const example = { |
| 248 | "age": 35, |
| 249 | "flags": [true, false, true, true], |
| 250 | "weight": 72.5, |
| 251 | "name": "Maxim", |
| 252 | "address": { |
| 253 | "city": "Bla", |
| 254 | "zip": "12345", |
| 255 | "countryCode": "XX", |
| 256 | } |
| 257 | }; |
| 258 | |
| 259 | function _assert(value) { |
| 260 | let buffer = flexbuffers.encode(value, 1); |
| 261 | let o = flexbuffers.toObject(buffer.buffer); |
| 262 | assert.deepStrictEqual(o, value); |
| 263 | } |
| 264 | |
| 265 | _assert(example); |
| 266 | _assert(0x100000001n); |
| 267 | } |
| 268 | |
| 269 | function testRoundTripWithBuilder() { |
| 270 | const example = { |
| 271 | "age": 35, |
| 272 | "flags": [true, false, true, true], |
| 273 | "weight": 72.5, |
| 274 | "name": "Maxim", |
| 275 | "address": { |
| 276 | "city": "Bla", |
| 277 | "zip": "12345", |
| 278 | "countryCode": "XX", |
| 279 | } |
| 280 | }; |
| 281 | |
| 282 | const builder = flexbuffers.builder(); |
| 283 | builder.startMap(); |
| 284 | |
| 285 | builder.addKey('age'); |
| 286 | builder.add(35); |
| 287 | |
| 288 | builder.addKey('flags'); |
| 289 | builder.startVector(); |
| 290 | builder.add(true); |
| 291 | builder.add(false); |
| 292 | builder.add(true); |
| 293 | builder.add(true); |
| 294 | builder.end(); |
| 295 | |
| 296 | builder.addKey("weight"); |
| 297 | builder.add(72.5); |
| 298 | |
| 299 | builder.addKey("name"); |
| 300 | builder.add("Maxim"); |
| 301 | |
| 302 | builder.addKey("address"); |
| 303 | |
| 304 | builder.startMap(); |
| 305 | builder.addKey("city"); |
| 306 | builder.add("Bla"); |
| 307 | builder.addKey("zip"); |
| 308 | builder.add("12345"); |
| 309 | builder.addKey("countryCode"); |
| 310 | builder.add("XX"); |
| 311 | builder.end(); |
| 312 | |
| 313 | builder.end(); |
| 314 | |
| 315 | const data = builder.finish(); |
| 316 | let o = flexbuffers.toObject(data.buffer); |
| 317 | assert.deepStrictEqual(o, example); |
| 318 | |
| 319 | let root = flexbuffers.toReference(data.buffer); |
| 320 | assert.strictEqual(root.isMap(), true); |
| 321 | assert.strictEqual(root.get("age").numericValue(), 35); |
| 322 | assert.strictEqual(root.get("age").intValue(), 35); |
| 323 | assert.strictEqual(root.get("name").stringValue(), "Maxim"); |
| 324 | assert.strictEqual(root.get("weight").floatValue(), 72.5); |
| 325 | assert.strictEqual(root.get("weight").numericValue(), 72.5); |
| 326 | let flags = root.get("flags"); |
| 327 | assert.strictEqual(flags.isVector(), true); |
| 328 | assert.strictEqual(flags.length(), 4); |
| 329 | assert.strictEqual(flags.get(0).boolValue(), true); |
| 330 | assert.strictEqual(flags.get(1).boolValue(), false); |
| 331 | assert.strictEqual(flags.get(2).boolValue(), true); |
| 332 | assert.strictEqual(flags.get(3).boolValue(), true); |
| 333 | |
| 334 | let address = root.get("address"); |
| 335 | assert.strictEqual(address.isMap(), true); |
| 336 | assert.strictEqual(address.length(), 3); |
| 337 | assert.strictEqual(address.get("city").stringValue(), "Bla"); |
| 338 | assert.strictEqual(address.get("zip").stringValue(), "12345"); |
| 339 | assert.strictEqual(address.get("countryCode").stringValue(), "XX"); |
| 340 | } |
| 341 | |
| 342 | function testGoldBuffer() { |
| 343 | const data = new Uint8Array(fs.readFileSync('gold_flexbuffer_example.bin')).buffer; |
| 344 | const b1 = flexbuffers.toReference(data).get("bools").get(1); |
| 345 | assert.strictEqual(b1.isBool(), true); |
| 346 | assert.strictEqual(b1.boolValue(), false); |
| 347 | |
| 348 | const blob = flexbuffers.toReference(data).get("vec").get(3); |
| 349 | assert.strictEqual(blob.isBlob(), true); |
| 350 | assert.deepStrictEqual(blob.blobValue(), new Uint8Array([77])); |
| 351 | |
| 352 | const o = flexbuffers.toObject(data); |
| 353 | assert.deepStrictEqual(o, { |
| 354 | bool: true, |
| 355 | bools: [true, false, true, false], |
| 356 | bar: [1, 2, 3], |
| 357 | bar3: [1, 2, 3], |
| 358 | foo: 100, |
| 359 | mymap: {foo:'Fred'}, |
| 360 | vec: [-100, 'Fred', 4, new Uint8Array([77]), false, 4] |
| 361 | }); |
| 362 | } |
| 363 | |
| 364 | function testBugWhereOffestWereStoredAsIntInsteadOfUInt() { |
| 365 | // Reported in https://github.com/google/flatbuffers/issues/5949#issuecomment-688421193 |
| 366 | const object = {'channels_in': 64, 'dilation_height_factor': 1, 'dilation_width_factor': 1, 'fused_activation_function': 1, 'pad_values': 1, 'padding': 0, 'stride_height': 1, 'stride_width': 1}; |
| 367 | let data1 = flexbuffers.encode(object); |
| 368 | const data = [99, 104, 97, 110, 110, 101, 108, 115, 95, 105, 110, 0, |
| 369 | 100, 105, 108, 97, 116, 105, 111, 110, 95, 104, 101, 105, 103, 104, 116, 95, 102, 97, 99, 116, 111, 114, 0, |
| 370 | 100, 105, 108, 97, 116, 105, 111, 110, 95, 119, 105, 100, 116, 104, 95, 102, 97, 99, 116, 111, 114, 0, |
| 371 | 102, 117, 115, 101, 100, 95, 97, 99, 116, 105, 118, 97, 116, 105, 111, 110, 95, 102, 117, 110, 99, 116, 105, 111, 110, 0, |
| 372 | 112, 97, 100, 95, 118, 97, 108, 117, 101, 115, 0, 112, 97, 100, 100, 105, 110, 103, 0, |
| 373 | 115, 116, 114, 105, 100, 101, 95, 104, 101, 105, 103, 104, 116, 0, |
| 374 | 115, 116, 114, 105, 100, 101, 95, 119, 105, 100, 116, 104, 0, |
| 375 | 8, 130, 119, 97, 76, 51, 41, 34, 21, 8, 1, 8, 64, 1, 1, 1, 1, 0, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 16, 36, 1]; |
| 376 | let object2 = flexbuffers.toObject(new Uint8Array(data).buffer); |
| 377 | let object1 = flexbuffers.toObject(new Uint8Array(data1).buffer); |
| 378 | assert.deepStrictEqual(object, object2); |
| 379 | assert.deepStrictEqual(object, object1); |
| 380 | assert.strictEqual(data.length, data1.length); |
| 381 | let ref = flexbuffers.toReference(new Uint8Array(data).buffer); |
| 382 | assert.strictEqual(ref.isMap(), true); |
| 383 | assert.strictEqual(ref.length(), 8); |
| 384 | assert.strictEqual(ref.get("channels_in").numericValue(), 64); |
| 385 | assert.strictEqual(ref.get("padding").isNumber(), true); |
| 386 | } |
| 387 | |
| 388 | main(); |
| 389 | |