1// Run this using JavaScriptTest.sh 2import assert from 'assert' 3import fs from 'fs' 4import * as flexbuffers from 'flatbuffers/js/flexbuffers' 5 6function main() { 7 testSingleValueBuffers(); 8 testGoldBuffer(); 9 testEncode(); 10 testIndirectAdd(); 11 testIndirectWithCache(); 12 testMapBuilder(); 13 testRoundTrip(); 14 testRoundTripWithBuilder(); 15 testDeduplicationOff(); 16 testBugWhereOffestWereStoredAsIntInsteadOfUInt(); 17 18 console.log('FlexBuffers test: completed successfully'); 19} 20 21function testSingleValueBuffers() { 22 { 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 54function 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 111function 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 146function 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 184function 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 234function 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 246function 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 269function 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 342function 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 364function 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 388main(); 389 390