| // Run this using JavaScriptTest.sh | |
| import assert from 'assert' | |
| import * as flexbuffers from 'flatbuffers/js/flexbuffers.js' | |
| import fs from 'fs' | |
| function main() { | |
| testSingleValueBuffers(); | |
| testGoldBuffer(); | |
| testEncode(); | |
| testIndirectAdd(); | |
| testIndirectWithCache(); | |
| testMapBuilder(); | |
| testRoundTrip(); | |
| testRoundTripWithBuilder(); | |
| testDeduplicationOff(); | |
| testBugWhereOffestWereStoredAsIntInsteadOfUInt(); | |
| testRootVector(); | |
| console.log('FlexBuffers test: completed successfully'); | |
| } | |
| function testRootVector() { | |
| // Root vector of strings | |
| const stringVec = ['a', 'b', 'c']; | |
| const bufStr = flexbuffers.encode(stringVec).buffer; | |
| const objStr = flexbuffers.toObject(bufStr); | |
| assert.deepStrictEqual(objStr, stringVec); | |
| // Root vector of numbers | |
| const numVec = [1, 2, 3, 4]; | |
| const bufNum = flexbuffers.encode(numVec).buffer; | |
| const objNum = flexbuffers.toObject(bufNum); | |
| assert.deepStrictEqual(objNum, numVec); | |
| // Root vector of mixed types | |
| const mixedVec = ['x', 42, true, null]; | |
| const bufMixed = flexbuffers.encode(mixedVec).buffer; | |
| const objMixed = flexbuffers.toObject(bufMixed); | |
| assert.deepStrictEqual(objMixed, mixedVec); | |
| } | |
| function testSingleValueBuffers() { | |
| { | |
| const ref = flexbuffers.toReference(new Uint8Array([0, 0, 1]).buffer); | |
| assert.strictEqual(true, ref.isNull()); | |
| } | |
| function _assert(object, buffer) { | |
| assert.deepStrictEqual( | |
| flexbuffers.toObject(new Uint8Array(buffer).buffer), object); | |
| } | |
| _assert(true, [1, 104, 1]); | |
| _assert(false, [0, 104, 1]); | |
| _assert(25, [25, 4, 1]); | |
| _assert(-25, [231, 4, 1]); | |
| _assert(230, [230, 8, 1]); | |
| _assert(230, [230, 0, 5, 2]); | |
| _assert(-1025, [255, 251, 5, 2]); | |
| _assert(1025, [1, 4, 9, 2]); | |
| _assert(2147483647, [255, 255, 255, 127, 6, 4]); | |
| _assert(-2147483648, [0, 0, 0, 128, 6, 4]); | |
| _assert(4294967295n, [255, 255, 255, 255, 0, 0, 0, 0, 7, 8]); | |
| _assert(9223372036854775807n, [255, 255, 255, 255, 255, 255, 255, 127, 7, 8]); | |
| _assert(-9223372036854775808n, [0, 0, 0, 0, 0, 0, 0, 128, 7, 8]); | |
| _assert( | |
| 18446744073709551615n, [255, 255, 255, 255, 255, 255, 255, 255, 11, 8]); | |
| _assert(4.5, [0, 0, 144, 64, 14, 4]); | |
| _assert(0.10000000149011612, [205, 204, 204, 61, 14, 4]); | |
| _assert(0.1, [154, 153, 153, 153, 153, 153, 185, 63, 15, 8]); | |
| _assert(-1025, [255, 251, 5, 2]); | |
| _assert('Maxim', [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]); | |
| _assert( | |
| 'hello 😱', | |
| [10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]); | |
| _assert({a: 12}, [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]); | |
| _assert( | |
| {'': 45, 'a': 12}, [0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]); | |
| } | |
| function testEncode() { | |
| function _assert(value, buffer) { | |
| assert.deepStrictEqual(flexbuffers.encode(value), new Uint8Array(buffer)); | |
| } | |
| _assert(null, [0, 0, 1]); | |
| _assert(true, [1, 104, 1]); | |
| _assert(false, [0, 104, 1]); | |
| _assert(1, [1, 4, 1]); | |
| _assert(230, [230, 0, 5, 2]); | |
| _assert(1025, [1, 4, 5, 2]); | |
| _assert(-1025, [255, 251, 5, 2]); | |
| _assert(0x100000001, [1, 0, 0, 0, 1, 0, 0, 0, 7, 8]); | |
| _assert(0.1, [154, 153, 153, 153, 153, 153, 185, 63, 15, 8]); | |
| _assert(0.5, [0, 0, 0, 63, 14, 4]); | |
| _assert(new Uint8Array([1, 2, 3]), [3, 1, 2, 3, 3, 100, 1]); | |
| _assert('Maxim', [5, 77, 97, 120, 105, 109, 0, 6, 20, 1]); | |
| _assert( | |
| 'hello 😱', | |
| [10, 104, 101, 108, 108, 111, 32, 240, 159, 152, 177, 0, 11, 20, 1]); | |
| _assert([1, 2], [1, 2, 2, 64, 1]); | |
| _assert([-1, 256], [255, 255, 0, 1, 4, 65, 1]); | |
| _assert([-45, 256000], [211, 255, 255, 255, 0, 232, 3, 0, 8, 66, 1]); | |
| _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 | |
| ]); | |
| _assert([1, 2, 4], [1, 2, 4, 3, 76, 1]); | |
| _assert([-1, 256, 4], [255, 255, 0, 1, 4, 0, 6, 77, 1]); | |
| _assert([[61], 64], [1, 61, 2, 2, 64, 44, 4, 4, 40, 1]); | |
| _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 | |
| ]); | |
| _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 | |
| ]); | |
| _assert([true, false, true], [3, 1, 0, 1, 3, 144, 1]); | |
| _assert(['foo', 1, -5, 1.3, true], [ | |
| 3, 102, 111, 111, 0, 0, 0, 0, 5, 0, 0, 0, 0, | |
| 0, 0, 0, 15, 0, 0, 0, 0, 0, 0, 0, 1, 0, | |
| 0, 0, 0, 0, 0, 0, 251, 255, 255, 255, 255, 255, 255, | |
| 255, 205, 204, 204, 204, 204, 204, 244, 63, 1, 0, 0, 0, | |
| 0, 0, 0, 0, 20, 4, 4, 15, 104, 45, 43, 1 | |
| ]); | |
| _assert([1, 3.3, 'max', true, null, false], [ | |
| 3, 109, 97, 120, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, | |
| 0, 1, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102, 102, | |
| 10, 64, 31, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 4, 15, 20, 104, 0, 104, 54, 43, 1 | |
| ]); | |
| _assert({'a': 12}, [97, 0, 1, 3, 1, 1, 1, 12, 4, 2, 36, 1]); | |
| _assert( | |
| {'a': 12, '': 45}, [0, 97, 0, 2, 4, 4, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1]); | |
| // JS currently does not support key vector offset sharing | |
| _assert([{'something': 12}, {'something': 45}], [ | |
| 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 1, 11, 1, 1, 1, | |
| 12, 4, 6, 1, 1, 45, 4, 2, 8, 4, 36, 36, 4, 40, 1 | |
| ]); | |
| } | |
| function testDeduplicationOff() { | |
| let buffer = flexbuffers.encode( | |
| [{'something': 12}, {'something': 45}], 1, true, true, false); | |
| assert.deepStrictEqual( | |
| buffer, new Uint8Array([ | |
| 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 1, 11, 1, 1, 1, 12, | |
| 4, 1, 18, 1, 1, 1, 45, 4, 2, 10, 4, 36, 36, 4, 40, 1 | |
| ])); | |
| buffer = flexbuffers.encode( | |
| [{'something': 12}, {'something': 45}], 1, true, false, false); | |
| assert.deepStrictEqual( | |
| buffer, new Uint8Array([ | |
| 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 1, 11, 1, 1, | |
| 1, 12, 4, 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 1, | |
| 11, 1, 1, 1, 45, 4, 2, 20, 4, 36, 36, 4, 40, 1 | |
| ])); | |
| buffer = flexbuffers.encode( | |
| ['something', 'something', 'dark'], 1, true, false, false); | |
| assert.deepStrictEqual( | |
| buffer, new Uint8Array([ | |
| 9, 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 4, | |
| 100, 97, 114, 107, 0, 3, 17, 18, 8, 3, 60, 1 | |
| ])); | |
| buffer = flexbuffers.encode( | |
| ['something', 'something', 'dark'], 1, false, false, false); | |
| assert.deepStrictEqual( | |
| buffer, new Uint8Array([ | |
| 9, 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 9, | |
| 115, 111, 109, 101, 116, 104, 105, 110, 103, 0, 4, 100, | |
| 97, 114, 107, 0, 3, 28, 18, 8, 3, 60, 1 | |
| ])); | |
| } | |
| function testIndirectAdd() { | |
| function _assertInt(buffer, value, indirect = false, cache = false) { | |
| const builder = flexbuffers.builder(); | |
| builder.addInt(value, indirect, cache); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| function _assertUInt(buffer, value, indirect = false, cache = false) { | |
| const builder = flexbuffers.builder(); | |
| builder.addUInt(value, indirect, cache); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| function _assertFloat(buffer, value, indirect = false, cache = false) { | |
| const builder = flexbuffers.builder(); | |
| builder.addFloat(value, indirect, cache); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| _assertInt([0, 4, 1], 0); | |
| _assertInt([0, 1, 24, 1], 0, true); | |
| _assertInt([255, 0, 5, 2], 255); | |
| _assertUInt([0, 8, 1], 0); | |
| _assertUInt([0, 1, 28, 1], 0, true); | |
| _assertUInt([255, 8, 1], 255); | |
| _assertUInt([185, 115, 175, 118, 250, 84, 8, 0, 11, 8], 2345234523452345); | |
| _assertUInt( | |
| [185, 115, 175, 118, 250, 84, 8, 0, 8, 31, 1], 2345234523452345, true); | |
| _assertInt([185, 115, 175, 118, 250, 84, 8, 0, 7, 8], 2345234523452345); | |
| _assertInt( | |
| [185, 115, 175, 118, 250, 84, 8, 0, 8, 27, 1], 2345234523452345, true); | |
| _assertFloat([154, 153, 153, 153, 153, 153, 185, 63, 15, 8], 0.1); | |
| _assertFloat([154, 153, 153, 153, 153, 153, 185, 63, 8, 35, 1], 0.1, true); | |
| _assertFloat([0, 0, 0, 0, 14, 4], 0); | |
| _assertFloat([0, 0, 0, 0, 4, 34, 1], 0, true); | |
| } | |
| function testIndirectWithCache() { | |
| function _assertInt(buffer, values) { | |
| const builder = flexbuffers.builder(); | |
| builder.startVector(); | |
| values.forEach(v => {builder.addInt(v, true, true)}); | |
| builder.end(); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| function _assertUInt(buffer, values) { | |
| const builder = flexbuffers.builder(); | |
| builder.startVector(); | |
| values.forEach(v => { | |
| builder.addUInt(v, true, true); | |
| }); | |
| builder.end(); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| function _assertFloat(buffer, values) { | |
| const builder = flexbuffers.builder(); | |
| builder.startVector(); | |
| values.forEach(v => { | |
| builder.addFloat(v, true, true); | |
| }); | |
| builder.end(); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual(data, new Uint8Array(buffer)); | |
| } | |
| _assertInt( | |
| [ | |
| 185, 115, 175, 118, 250, 84, 8, 0, 4, 9, | |
| 10, 11, 12, 27, 27, 27, 27, 8, 40, 1 | |
| ], | |
| [2345234523452345, 2345234523452345, 2345234523452345, 2345234523452345]); | |
| _assertUInt( | |
| [ | |
| 185, 115, 175, 118, 250, 84, 8, 0, 4, 9, | |
| 10, 11, 12, 31, 31, 31, 31, 8, 40, 1 | |
| ], | |
| [2345234523452345, 2345234523452345, 2345234523452345, 2345234523452345]); | |
| _assertFloat( | |
| [ | |
| 154, 153, 153, 153, 153, 153, 185, 63, 4, 9, | |
| 10, 11, 12, 35, 35, 35, 35, 8, 40, 1 | |
| ], | |
| [0.1, 0.1, 0.1, 0.1]); | |
| } | |
| function testMapBuilder() { | |
| const builder = flexbuffers.builder(); | |
| builder.startMap(); | |
| builder.addKey('a'); | |
| builder.add(12); | |
| builder.addKey(''); | |
| builder.add(45); | |
| builder.end(); | |
| const data = builder.finish(); | |
| assert.deepStrictEqual( | |
| data, | |
| new Uint8Array([97, 0, 0, 2, 2, 5, 2, 1, 2, 45, 12, 4, 4, 4, 36, 1])); | |
| } | |
| function testRoundTrip() { | |
| const example = { | |
| 'age': 35, | |
| 'flags': [true, false, true, true], | |
| 'weight': 72.5, | |
| 'name': 'Maxim', | |
| 'address': { | |
| 'city': 'Bla', | |
| 'zip': '12345', | |
| 'countryCode': 'XX', | |
| } | |
| }; | |
| function _assert(value) { | |
| let buffer = flexbuffers.encode(value, 1); | |
| let o = flexbuffers.toObject(buffer.buffer); | |
| assert.deepStrictEqual(o, value); | |
| } | |
| _assert(example); | |
| _assert(0x100000001n); | |
| _assert({test_number: 72.6}) | |
| } | |
| function testRoundTripWithBuilder() { | |
| const example = { | |
| 'age': 35, | |
| 'flags': [true, false, true, true], | |
| 'weight': 72.5, | |
| 'name': 'Maxim', | |
| 'address': { | |
| 'city': 'Bla', | |
| 'zip': '12345', | |
| 'countryCode': 'XX', | |
| } | |
| }; | |
| const builder = flexbuffers.builder(); | |
| builder.startMap(); | |
| builder.addKey('age'); | |
| builder.add(35); | |
| builder.addKey('flags'); | |
| builder.startVector(); | |
| builder.add(true); | |
| builder.add(false); | |
| builder.add(true); | |
| builder.add(true); | |
| builder.end(); | |
| builder.addKey('weight'); | |
| builder.add(72.5); | |
| builder.addKey('name'); | |
| builder.add('Maxim'); | |
| builder.addKey('address'); | |
| builder.startMap(); | |
| builder.addKey('city'); | |
| builder.add('Bla'); | |
| builder.addKey('zip'); | |
| builder.add('12345'); | |
| builder.addKey('countryCode'); | |
| builder.add('XX'); | |
| builder.end(); | |
| builder.end(); | |
| const data = builder.finish(); | |
| let o = flexbuffers.toObject(data.buffer); | |
| assert.deepStrictEqual(o, example); | |
| let root = flexbuffers.toReference(data.buffer); | |
| assert.strictEqual(root.isMap(), true); | |
| assert.strictEqual(root.get('age').numericValue(), 35); | |
| assert.strictEqual(root.get('age').intValue(), 35); | |
| assert.strictEqual(root.get('name').stringValue(), 'Maxim'); | |
| assert.strictEqual(root.get('weight').floatValue(), 72.5); | |
| assert.strictEqual(root.get('weight').numericValue(), 72.5); | |
| let flags = root.get('flags'); | |
| assert.strictEqual(flags.isVector(), true); | |
| assert.strictEqual(flags.length(), 4); | |
| assert.strictEqual(flags.get(0).boolValue(), true); | |
| assert.strictEqual(flags.get(1).boolValue(), false); | |
| assert.strictEqual(flags.get(2).boolValue(), true); | |
| assert.strictEqual(flags.get(3).boolValue(), true); | |
| let address = root.get('address'); | |
| assert.strictEqual(address.isMap(), true); | |
| assert.strictEqual(address.length(), 3); | |
| assert.strictEqual(address.get('city').stringValue(), 'Bla'); | |
| assert.strictEqual(address.get('zip').stringValue(), '12345'); | |
| assert.strictEqual(address.get('countryCode').stringValue(), 'XX'); | |
| } | |
| function testGoldBuffer() { | |
| const data = | |
| new Uint8Array(fs.readFileSync('../gold_flexbuffer_example.bin')).buffer; | |
| const b1 = flexbuffers.toReference(data).get('bools').get(1); | |
| assert.strictEqual(b1.isBool(), true); | |
| assert.strictEqual(b1.boolValue(), false); | |
| const blob = flexbuffers.toReference(data).get('vec').get(3); | |
| assert.strictEqual(blob.isBlob(), true); | |
| assert.deepStrictEqual(blob.blobValue(), new Uint8Array([77])); | |
| const o = flexbuffers.toObject(data); | |
| assert.deepStrictEqual(o, { | |
| bool: true, | |
| bools: [true, false, true, false], | |
| bar: [1, 2, 3], | |
| bar3: [1, 2, 3], | |
| foo: 100, | |
| mymap: {foo: 'Fred'}, | |
| vec: [-100, 'Fred', 4, new Uint8Array([77]), false, 4] | |
| }); | |
| } | |
| function testBugWhereOffestWereStoredAsIntInsteadOfUInt() { | |
| // Reported in | |
| // https://github.com/google/flatbuffers/issues/5949#issuecomment-688421193 | |
| 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 | |
| }; | |
| let data1 = flexbuffers.encode(object); | |
| const data = [ | |
| 99, 104, 97, 110, 110, 101, 108, 115, 95, 105, 110, 0, 100, 105, 108, | |
| 97, 116, 105, 111, 110, 95, 104, 101, 105, 103, 104, 116, 95, 102, 97, | |
| 99, 116, 111, 114, 0, 100, 105, 108, 97, 116, 105, 111, 110, 95, 119, | |
| 105, 100, 116, 104, 95, 102, 97, 99, 116, 111, 114, 0, 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, 112, 97, 100, 95, 118, 97, 108, | |
| 117, 101, 115, 0, 112, 97, 100, 100, 105, 110, 103, 0, 115, 116, 114, | |
| 105, 100, 101, 95, 104, 101, 105, 103, 104, 116, 0, 115, 116, 114, 105, | |
| 100, 101, 95, 119, 105, 100, 116, 104, 0, 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 | |
| ]; | |
| let object2 = flexbuffers.toObject(new Uint8Array(data).buffer); | |
| let object1 = flexbuffers.toObject(new Uint8Array(data1).buffer); | |
| assert.deepStrictEqual(object, object2); | |
| assert.deepStrictEqual(object, object1); | |
| assert.strictEqual(data.length, data1.length); | |
| let ref = flexbuffers.toReference(new Uint8Array(data).buffer); | |
| assert.strictEqual(ref.isMap(), true); | |
| assert.strictEqual(ref.length(), 8); | |
| assert.strictEqual(ref.get('channels_in').numericValue(), 64); | |
| assert.strictEqual(ref.get('padding').isNumber(), true); | |
| } | |
| main(); |