2 * Copyright 2014 Google Inc. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 import java.util.Arrays;
18 import java.math.BigInteger;
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.nio.channels.FileChannel;
24 import java.util.HashMap;
25 import MyGame.Example.*;
27 import NamespaceA.NamespaceB.*;
28 import com.google.flatbuffers.ByteBufferUtil;
29 import static com.google.flatbuffers.Constants.*;
30 import com.google.flatbuffers.FlatBufferBuilder;
31 import com.google.flatbuffers.ByteVector;
32 import com.google.flatbuffers.FlexBuffersBuilder;
33 import com.google.flatbuffers.FlexBuffers;
34 import com.google.flatbuffers.StringVector;
35 import com.google.flatbuffers.UnionVector;
36 import MyGame.MonsterExtra;
39 public static void main(String[] args) {
41 // First, let's test reading a FlatBuffer generated by C++ code:
42 // This file was generated from monsterdata_test.json
45 File file = new File("monsterdata_test.mon");
46 RandomAccessFile f = null;
48 f = new RandomAccessFile(file, "r");
49 data = new byte[(int)f.length()];
52 } catch(java.io.IOException e) {
53 System.out.println("FlatBuffers test: couldn't read file");
59 ByteBuffer bb = ByteBuffer.wrap(data);
62 // Second, let's create a FlatBuffer from scratch in Java, and test it also.
63 // We use an initial size of 1 to exercise the reallocation algorithm,
64 // normally a size larger than the typical FlatBuffer you generate would be
65 // better for performance.
66 FlatBufferBuilder fbb = new FlatBufferBuilder(1);
68 TestBuilderBasics(fbb, true);
69 TestBuilderBasics(fbb, false);
71 TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
73 TestNamespaceNesting();
75 TestNestedFlatBuffer();
77 TestCreateByteVector();
79 TestCreateUninitializedVector();
81 TestByteBufferFactory();
83 TestSizedInputStream();
87 TestFixedLengthArrays();
91 System.out.println("FlatBuffers test: completed successfully");
94 static void TestEnums() {
95 TestEq(Color.name(Color.Red), "Red");
96 TestEq(Color.name(Color.Blue), "Blue");
97 TestEq(Any.name(Any.NONE), "NONE");
98 TestEq(Any.name(Any.Monster), "Monster");
101 static void TestBuffer(ByteBuffer bb) {
102 TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
104 Monster monster = Monster.getRootAsMonster(bb);
106 TestEq(monster.hp(), (short)80);
107 TestEq(monster.mana(), (short)150); // default
109 TestEq(monster.name(), "MyMonster");
110 // monster.friendly() // can't access, deprecated
112 Vec3 pos = monster.pos();
113 TestEq(pos.x(), 1.0f);
114 TestEq(pos.y(), 2.0f);
115 TestEq(pos.z(), 3.0f);
116 TestEq(pos.test1(), 3.0);
117 // issue: int != byte
118 TestEq(pos.test2(), (int) Color.Green);
119 Test t = pos.test3();
120 TestEq(t.a(), (short)5);
121 TestEq(t.b(), (byte)6);
123 TestEq(monster.testType(), (byte)Any.Monster);
124 Monster monster2 = new Monster();
125 TestEq(monster.test(monster2) != null, true);
126 TestEq(monster2.name(), "Fred");
128 TestEq(monster.inventoryLength(), 5);
130 for (int i = 0; i < monster.inventoryLength(); i++)
131 invsum += monster.inventory(i);
134 // Method using a vector access object:
135 ByteVector inventoryVector = monster.inventoryVector();
136 TestEq(inventoryVector.length(), 5);
138 for (int i = 0; i < inventoryVector.length(); i++)
139 invsum += inventoryVector.getAsUnsigned(i);
142 // Alternative way of accessing a vector:
143 ByteBuffer ibb = monster.inventoryAsByteBuffer();
145 while (ibb.position() < ibb.limit())
149 Test test_0 = monster.test4(0);
150 Test test_1 = monster.test4(1);
151 TestEq(monster.test4Length(), 2);
152 TestEq(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
154 Test.Vector test4Vector = monster.test4Vector();
155 test_0 = test4Vector.get(0);
156 test_1 = test4Vector.get(1);
157 TestEq(test4Vector.length(), 2);
158 TestEq(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
160 TestEq(monster.testarrayofstringLength(), 2);
161 TestEq(monster.testarrayofstring(0),"test1");
162 TestEq(monster.testarrayofstring(1),"test2");
164 // Method using a vector access object:
165 StringVector testarrayofstringVector = monster.testarrayofstringVector();
166 TestEq(testarrayofstringVector.length(), 2);
167 TestEq(testarrayofstringVector.get(0),"test1");
168 TestEq(testarrayofstringVector.get(1),"test2");
170 TestEq(monster.testbool(), true);
173 // this method checks additional fields not present in the binary buffer read from file
174 // these new tests are performed on top of the regular tests
175 static void TestExtendedBuffer(ByteBuffer bb) {
178 Monster monster = Monster.getRootAsMonster(bb);
180 TestEq(monster.testhashu32Fnv1(), Integer.MAX_VALUE + 1L);
183 static void TestNamespaceNesting() {
184 // reference / manipulate these to verify compilation
185 FlatBufferBuilder fbb = new FlatBufferBuilder(1);
187 TableInNestedNS.startTableInNestedNS(fbb);
188 TableInNestedNS.addFoo(fbb, 1234);
189 int nestedTableOff = TableInNestedNS.endTableInNestedNS(fbb);
191 TableInFirstNS.startTableInFirstNS(fbb);
192 TableInFirstNS.addFooTable(fbb, nestedTableOff);
193 int off = TableInFirstNS.endTableInFirstNS(fbb);
196 static void TestNestedFlatBuffer() {
197 final String nestedMonsterName = "NestedMonsterName";
198 final short nestedMonsterHp = 600;
199 final short nestedMonsterMana = 1024;
201 FlatBufferBuilder fbb1 = new FlatBufferBuilder(16);
202 int str1 = fbb1.createString(nestedMonsterName);
203 Monster.startMonster(fbb1);
204 Monster.addName(fbb1, str1);
205 Monster.addHp(fbb1, nestedMonsterHp);
206 Monster.addMana(fbb1, nestedMonsterMana);
207 int monster1 = Monster.endMonster(fbb1);
208 Monster.finishMonsterBuffer(fbb1, monster1);
209 byte[] fbb1Bytes = fbb1.sizedByteArray();
212 FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
213 int str2 = fbb2.createString("My Monster");
214 int nestedBuffer = Monster.createTestnestedflatbufferVector(fbb2, fbb1Bytes);
215 Monster.startMonster(fbb2);
216 Monster.addName(fbb2, str2);
217 Monster.addHp(fbb2, (short)50);
218 Monster.addMana(fbb2, (short)32);
219 Monster.addTestnestedflatbuffer(fbb2, nestedBuffer);
220 int monster = Monster.endMonster(fbb2);
221 Monster.finishMonsterBuffer(fbb2, monster);
223 // Now test the data extracted from the nested buffer
224 Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
225 Monster nestedMonster = mons.testnestedflatbufferAsMonster();
227 TestEq(nestedMonsterMana, nestedMonster.mana());
228 TestEq(nestedMonsterHp, nestedMonster.hp());
229 TestEq(nestedMonsterName, nestedMonster.name());
232 static void TestCreateByteVector() {
233 FlatBufferBuilder fbb = new FlatBufferBuilder(16);
234 int str = fbb.createString("MyMonster");
235 byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
236 int vec = fbb.createByteVector(inventory);
237 Monster.startMonster(fbb);
238 Monster.addInventory(fbb, vec);
239 Monster.addName(fbb, str);
240 int monster1 = Monster.endMonster(fbb);
241 Monster.finishMonsterBuffer(fbb, monster1);
242 Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
244 TestEq(monsterObject.inventory(1), (int)inventory[1]);
245 TestEq(monsterObject.inventoryLength(), inventory.length);
246 ByteVector inventoryVector = monsterObject.inventoryVector();
247 TestEq(inventoryVector.getAsUnsigned(1), (int)inventory[1]);
248 TestEq(inventoryVector.length(), inventory.length);
250 TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
253 static void TestCreateUninitializedVector() {
254 FlatBufferBuilder fbb = new FlatBufferBuilder(16);
255 int str = fbb.createString("MyMonster");
256 byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
257 ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
258 for (byte i:inventory) {
261 int vec = fbb.endVector();
262 Monster.startMonster(fbb);
263 Monster.addInventory(fbb, vec);
264 Monster.addName(fbb, str);
265 int monster1 = Monster.endMonster(fbb);
266 Monster.finishMonsterBuffer(fbb, monster1);
267 Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
269 TestEq(monsterObject.inventory(1), (int)inventory[1]);
270 TestEq(monsterObject.inventoryLength(), inventory.length);
271 ByteVector inventoryVector = monsterObject.inventoryVector();
272 TestEq(inventoryVector.getAsUnsigned(1), (int)inventory[1]);
273 TestEq(inventoryVector.length(), inventory.length);
274 TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
277 static void TestByteBufferFactory() {
278 final class MappedByteBufferFactory extends FlatBufferBuilder.ByteBufferFactory {
280 public ByteBuffer newByteBuffer(int capacity) {
283 RandomAccessFile f = new RandomAccessFile("javatest.bin", "rw");
284 bb = f.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, capacity).order(ByteOrder.LITTLE_ENDIAN);
286 } catch(Throwable e) {
287 System.out.println("FlatBuffers test: couldn't map ByteBuffer to a file");
294 FlatBufferBuilder fbb = new FlatBufferBuilder(1, new MappedByteBufferFactory());
296 TestBuilderBasics(fbb, false);
299 static void TestSizedInputStream() {
300 // Test on default FlatBufferBuilder that uses HeapByteBuffer
301 FlatBufferBuilder fbb = new FlatBufferBuilder(1);
303 TestBuilderBasics(fbb, false);
305 InputStream in = fbb.sizedInputStream();
306 byte[] array = fbb.sizedByteArray();
310 while (currentVal != -1 && count < array.length) {
312 currentVal = in.read();
313 } catch(java.io.IOException e) {
314 System.out.println("FlatBuffers test: couldn't read from InputStream");
317 TestEq((byte)currentVal, array[count]);
320 TestEq(count, array.length);
323 static void TestBuilderBasics(FlatBufferBuilder fbb, boolean sizePrefix) {
324 int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
325 int[] off = new int[3];
326 Monster.startMonster(fbb);
327 Monster.addName(fbb, names[0]);
328 off[0] = Monster.endMonster(fbb);
329 Monster.startMonster(fbb);
330 Monster.addName(fbb, names[1]);
331 off[1] = Monster.endMonster(fbb);
332 Monster.startMonster(fbb);
333 Monster.addName(fbb, names[2]);
334 off[2] = Monster.endMonster(fbb);
335 int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
337 // We set up the same values as monsterdata.json:
339 int str = fbb.createString("MyMonster");
341 int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
343 int fred = fbb.createString("Fred");
344 Monster.startMonster(fbb);
345 Monster.addName(fbb, fred);
346 int mon2 = Monster.endMonster(fbb);
348 Monster.startTest4Vector(fbb, 2);
349 Test.createTest(fbb, (short)10, (byte)20);
350 Test.createTest(fbb, (short)30, (byte)40);
351 int test4 = fbb.endVector();
353 int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
354 fbb.createString("test1"),
355 fbb.createString("test2")
358 Monster.startMonster(fbb);
359 Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
360 Color.Green, (short)5, (byte)6));
361 Monster.addHp(fbb, (short)80);
362 Monster.addName(fbb, str);
363 Monster.addInventory(fbb, inv);
364 Monster.addTestType(fbb, (byte)Any.Monster);
365 Monster.addTest(fbb, mon2);
366 Monster.addTest4(fbb, test4);
367 Monster.addTestarrayofstring(fbb, testArrayOfString);
368 Monster.addTestbool(fbb, true);
369 Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
370 Monster.addTestarrayoftables(fbb, sortMons);
371 int mon = Monster.endMonster(fbb);
374 Monster.finishSizePrefixedMonsterBuffer(fbb, mon);
376 Monster.finishMonsterBuffer(fbb, mon);
379 // Write the result to a file for debugging purposes:
380 // Note that the binaries are not necessarily identical, since the JSON
381 // parser may serialize in a slightly different order than the above
382 // Java code. They are functionally equivalent though.
385 String filename = "monsterdata_java_wire" + (sizePrefix ? "_sp" : "") + ".mon";
386 FileChannel fc = new FileOutputStream(filename).getChannel();
387 fc.write(fbb.dataBuffer().duplicate());
389 } catch(java.io.IOException e) {
390 System.out.println("FlatBuffers test: couldn't write file");
395 ByteBuffer dataBuffer = fbb.dataBuffer();
397 TestEq(ByteBufferUtil.getSizePrefix(dataBuffer) + SIZE_PREFIX_LENGTH,
398 dataBuffer.remaining());
399 dataBuffer = ByteBufferUtil.removeSizePrefix(dataBuffer);
401 TestExtendedBuffer(dataBuffer);
403 // Make sure it also works with read only ByteBuffers. This is slower,
404 // since creating strings incurs an additional copy
405 // (see Table.__string).
406 TestExtendedBuffer(dataBuffer.asReadOnlyBuffer());
410 //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
411 // revert to original values after testing
412 Monster monster = Monster.getRootAsMonster(dataBuffer);
414 // mana is optional and does not exist in the buffer so the mutation should fail
415 // the mana field should retain its default value
416 TestEq(monster.mutateMana((short)10), false);
417 TestEq(monster.mana(), (short)150);
419 // Accessing a vector of sorted by the key tables
420 TestEq(monster.testarrayoftables(0).name(), "Barney");
421 TestEq(monster.testarrayoftables(1).name(), "Frodo");
422 TestEq(monster.testarrayoftables(2).name(), "Wilma");
423 Monster.Vector testarrayoftablesVector = monster.testarrayoftablesVector();
424 TestEq(testarrayoftablesVector.get(0).name(), "Barney");
425 TestEq(testarrayoftablesVector.get(1).name(), "Frodo");
426 TestEq(testarrayoftablesVector.get(2).name(), "Wilma");
428 // Example of searching for a table by the key
429 TestEq(monster.testarrayoftablesByKey("Frodo").name(), "Frodo");
430 TestEq(monster.testarrayoftablesByKey("Barney").name(), "Barney");
431 TestEq(monster.testarrayoftablesByKey("Wilma").name(), "Wilma");
432 TestEq(testarrayoftablesVector.getByKey("Frodo").name(), "Frodo");
433 TestEq(testarrayoftablesVector.getByKey("Barney").name(), "Barney");
434 TestEq(testarrayoftablesVector.getByKey("Wilma").name(), "Wilma");
436 // testType is an existing field and mutating it should succeed
437 TestEq(monster.testType(), (byte)Any.Monster);
438 TestEq(monster.mutateTestType(Any.NONE), true);
439 TestEq(monster.testType(), (byte)Any.NONE);
440 TestEq(monster.mutateTestType(Any.Monster), true);
441 TestEq(monster.testType(), (byte)Any.Monster);
443 //mutate the inventory vector
444 TestEq(monster.mutateInventory(0, 1), true);
445 TestEq(monster.mutateInventory(1, 2), true);
446 TestEq(monster.mutateInventory(2, 3), true);
447 TestEq(monster.mutateInventory(3, 4), true);
448 TestEq(monster.mutateInventory(4, 5), true);
450 for (int i = 0; i < monster.inventoryLength(); i++) {
451 TestEq(monster.inventory(i), i + 1);
453 ByteVector inventoryVector = monster.inventoryVector();
454 for (int i = 0; i < inventoryVector.length(); i++) {
455 TestEq((int)inventoryVector.get(i), i + 1);
459 TestEq(monster.mutateInventory(0, 0), true);
460 TestEq(monster.mutateInventory(1, 1), true);
461 TestEq(monster.mutateInventory(2, 2), true);
462 TestEq(monster.mutateInventory(3, 3), true);
463 TestEq(monster.mutateInventory(4, 4), true);
465 // get a struct field and edit one of its fields
466 Vec3 pos = monster.pos();
467 TestEq(pos.x(), 1.0f);
469 TestEq(pos.x(), 55.0f);
471 TestEq(pos.x(), 1.0f);
474 static void TestVectorOfUnions() {
475 final FlatBufferBuilder fbb = new FlatBufferBuilder();
477 final int swordAttackDamage = 1;
479 final int[] characterVector = new int[] {
480 Attacker.createAttacker(fbb, swordAttackDamage),
483 final byte[] characterTypeVector = new byte[]{
487 Movie.finishMovieBuffer(
493 Movie.createCharactersTypeVector(fbb, characterTypeVector),
494 Movie.createCharactersVector(fbb, characterVector)
498 final Movie movie = Movie.getRootAsMovie(fbb.dataBuffer());
499 ByteVector charactersTypeByteVector = movie.charactersTypeVector();
500 UnionVector charactersVector = movie.charactersVector();
502 TestEq(movie.charactersTypeLength(), characterTypeVector.length);
503 TestEq(charactersTypeByteVector.length(), characterTypeVector.length);
504 TestEq(movie.charactersLength(), characterVector.length);
505 TestEq(charactersVector.length(), characterVector.length);
507 TestEq(movie.charactersType(0), characterTypeVector[0]);
508 TestEq(charactersTypeByteVector.get(0), characterTypeVector[0]);
510 TestEq(((Attacker)movie.characters(new Attacker(), 0)).swordAttackDamage(), swordAttackDamage);
513 static void TestFixedLengthArrays() {
514 FlatBufferBuilder builder = new FlatBufferBuilder(0);
517 int[] b = new int[15];
519 int[][] d_a = new int[2][2];
520 byte[] d_b = new byte[2];
521 byte[][] d_c = new byte[2][2];
522 long[][] d_d = new long[2][2];
524 long[] f = new long[2];
527 for (int i = 0; i < 15; i++) b[i] = i;
535 d_c[0][0] = TestEnum.A;
536 d_c[0][1] = TestEnum.B;
537 d_c[1][0] = TestEnum.C;
538 d_c[1][1] = TestEnum.B;
547 int arrayOffset = ArrayStruct.createArrayStruct(builder,
548 a, b, c, d_a, d_b, d_c, d_d, e, f);
550 // Create a table with the ArrayStruct.
551 ArrayTable.startArrayTable(builder);
552 ArrayTable.addA(builder, arrayOffset);
553 int tableOffset = ArrayTable.endArrayTable(builder);
555 ArrayTable.finishArrayTableBuffer(builder, tableOffset);
557 ArrayTable table = ArrayTable.getRootAsArrayTable(builder.dataBuffer());
558 NestedStruct nested = new NestedStruct();
560 TestEq(table.a().a(), 0.5f);
561 for (int i = 0; i < 15; i++) TestEq(table.a().b(i), i);
562 TestEq(table.a().c(), (byte)1);
563 TestEq(table.a().d(nested, 0).a(0), 1);
564 TestEq(table.a().d(nested, 0).a(1), 2);
565 TestEq(table.a().d(nested, 1).a(0), 3);
566 TestEq(table.a().d(nested, 1).a(1), 4);
567 TestEq(table.a().d(nested, 0).b(), TestEnum.B);
568 TestEq(table.a().d(nested, 1).b(), TestEnum.C);
569 TestEq(table.a().d(nested, 0).c(0), TestEnum.A);
570 TestEq(table.a().d(nested, 0).c(1), TestEnum.B);
571 TestEq(table.a().d(nested, 1).c(0), TestEnum.C);
572 TestEq(table.a().d(nested, 1).c(1), TestEnum.B);
573 TestEq(table.a().d(nested, 0).d(0), (long)-1);
574 TestEq(table.a().d(nested, 0).d(1), (long)1);
575 TestEq(table.a().d(nested, 1).d(0), (long)-2);
576 TestEq(table.a().d(nested, 1).d(1), (long)2);
577 TestEq(table.a().e(), 2);
578 TestEq(table.a().f(0), (long)-1);
579 TestEq(table.a().f(1), (long)1);
582 public static void testFlexBuffersTest() {
583 FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
584 FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
586 // Write the equivalent of:
587 // { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ],
588 // foo: 100, bool: true, mymap: { foo: "Fred" } }
589 // It's possible to do this without std::function support as well.
590 int map1 = builder.startMap();
592 int vec1 = builder.startVector();
593 builder.putInt(-100);
594 builder.putString("Fred");
595 builder.putBlob(new byte[]{(byte) 77});
596 builder.putBoolean(false);
597 builder.putInt(Long.MAX_VALUE);
599 int map2 = builder.startMap();
600 builder.putInt("test", 200);
601 builder.endMap(null, map2);
603 builder.putFloat(150.9);
604 builder.putFloat(150.9999998);
605 builder.endVector("vec", vec1, false, false);
607 vec1 = builder.startVector();
611 builder.endVector("bar", vec1, true, false);
613 vec1 = builder.startVector();
614 builder.putBoolean(true);
615 builder.putBoolean(false);
616 builder.putBoolean(true);
617 builder.putBoolean(false);
618 builder.endVector("bools", vec1, true, false);
620 builder.putBoolean("bool", true);
621 builder.putFloat("foo", 100);
623 map2 = builder.startMap();
624 builder.putString("bar", "Fred"); // Testing key and string reuse.
625 builder.putInt("int", -120);
626 builder.putFloat("float", -123.0f);
627 builder.putBlob("blob", new byte[]{ 65, 67 });
628 builder.endMap("mymap", map2);
630 builder.endMap(null, map1);
633 FlexBuffers.Map m = FlexBuffers.getRoot(builder.getBuffer()).asMap();
637 // test empty (an null)
638 TestEq(m.get("no_key").asString(), ""); // empty if fail
639 TestEq(m.get("no_key").asMap(), FlexBuffers.Map.empty()); // empty if fail
640 TestEq(m.get("no_key").asKey(), FlexBuffers.Key.empty()); // empty if fail
641 TestEq(m.get("no_key").asVector(), FlexBuffers.Vector.empty()); // empty if fail
642 TestEq(m.get("no_key").asBlob(), FlexBuffers.Blob.empty()); // empty if fail
643 assert(m.get("no_key").asVector().isEmpty()); // empty if fail
645 // testing "vec" field
646 FlexBuffers.Vector vec = m.get("vec").asVector();
647 TestEq(vec.size(), 8);
648 TestEq(vec.get(0).asLong(), (long) -100);
649 TestEq(vec.get(1).asString(), "Fred");
650 TestEq(vec.get(2).isBlob(), true);
651 TestEq(vec.get(2).asBlob().size(), 1);
652 TestEq(vec.get(2).asBlob().data().get(0), (byte) 77);
653 TestEq(vec.get(3).isBoolean(), true); // Check if type is a bool
654 TestEq(vec.get(3).asBoolean(), false); // Check if value is false
655 TestEq(vec.get(4).asLong(), Long.MAX_VALUE);
656 TestEq(vec.get(5).isMap(), true);
657 TestEq(vec.get(5).asMap().get("test").asInt(), 200);
658 TestEq(Float.compare((float)vec.get(6).asFloat(), 150.9f), 0);
659 TestEq(Double.compare(vec.get(7).asFloat(), 150.9999998), 0);
660 TestEq((long)0, (long)vec.get(1).asLong()); //conversion fail returns 0 as C++
663 FlexBuffers.Vector tvec = m.get("bar").asVector();
664 TestEq(tvec.size(), 3);
665 TestEq(tvec.get(0).asInt(), 1);
666 TestEq(tvec.get(1).asInt(), 2);
667 TestEq(tvec.get(2).asInt(), 3);
668 TestEq(((FlexBuffers.TypedVector) tvec).getElemType(), FlexBuffers.FBT_INT);
671 FlexBuffers.Vector bvec = m.get("bools").asVector();
672 TestEq(bvec.size(), 4);
673 TestEq(bvec.get(0).asBoolean(), true);
674 TestEq(bvec.get(1).asBoolean(), false);
675 TestEq(bvec.get(2).asBoolean(), true);
676 TestEq(bvec.get(3).asBoolean(), false);
677 TestEq(((FlexBuffers.TypedVector) bvec).getElemType(), FlexBuffers.FBT_BOOL);
680 TestEq((float)m.get("foo").asFloat(), (float) 100);
681 TestEq(m.get("unknown").isNull(), true);
684 FlexBuffers.Map mymap = m.get("mymap").asMap();
685 TestEq(mymap.keys().get(0), m.keys().get(0)); // These should be equal by pointer equality, since key and value are shared.
686 TestEq(mymap.keys().get(0).toString(), "bar");
687 TestEq(mymap.values().get(0).asString(), vec.get(1).asString());
688 TestEq(mymap.get("int").asInt(), -120);
689 TestEq((float)mymap.get("float").asFloat(), -123.0f);
690 TestEq(Arrays.equals(mymap.get("blob").asBlob().getBytes(), new byte[]{ 65, 67 }), true);
691 TestEq(mymap.get("blob").asBlob().toString(), "AC");
692 TestEq(mymap.get("blob").toString(), "\"AC\"");
695 public static void testSingleElementBoolean() {
696 FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(100));
697 builder.putBoolean(true);
698 ByteBuffer b = builder.finish();
699 assert(FlexBuffers.getRoot(b).asBoolean());
702 public static void testSingleElementByte() {
703 FlexBuffersBuilder builder = new FlexBuffersBuilder();
705 ByteBuffer b = builder.finish();
706 TestEq(10, FlexBuffers.getRoot(b).asInt());
709 public static void testSingleElementShort() {
710 FlexBuffersBuilder builder = new FlexBuffersBuilder();
711 builder.putInt(Short.MAX_VALUE);
712 ByteBuffer b = builder.finish();
713 TestEq(Short.MAX_VALUE, (short)FlexBuffers.getRoot(b).asInt());
716 public static void testSingleElementInt() {
717 FlexBuffersBuilder builder = new FlexBuffersBuilder();
718 builder.putInt(Integer.MIN_VALUE);
719 ByteBuffer b = builder.finish();
720 TestEq(Integer.MIN_VALUE, FlexBuffers.getRoot(b).asInt());
723 public static void testSingleElementLong() {
724 FlexBuffersBuilder builder = new FlexBuffersBuilder();
725 builder.putInt(Long.MAX_VALUE);
726 ByteBuffer b = builder.finish();
727 TestEq(Long.MAX_VALUE, FlexBuffers.getRoot(b).asLong());
730 public static void testSingleElementFloat() {
731 FlexBuffersBuilder builder = new FlexBuffersBuilder();
732 builder.putFloat(Float.MAX_VALUE);
733 ByteBuffer b = builder.finish();
734 TestEq(Float.compare(Float.MAX_VALUE, (float) FlexBuffers.getRoot(b).asFloat()), 0);
737 public static void testSingleElementDouble() {
738 FlexBuffersBuilder builder = new FlexBuffersBuilder();
739 builder.putFloat(Double.MAX_VALUE);
740 ByteBuffer b = builder.finish();
741 TestEq(Double.compare(Double.MAX_VALUE, FlexBuffers.getRoot(b).asFloat()), 0);
744 public static void testSingleElementString() {
745 FlexBuffersBuilder builder = new FlexBuffersBuilder();
746 builder.putString("wow");
747 ByteBuffer b = builder.finish();
748 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
749 TestEq(FlexBuffers.FBT_STRING, r.getType());
750 TestEq("wow", r.asString());
753 public static void testSingleElementBlob() {
754 FlexBuffersBuilder builder = new FlexBuffersBuilder();
755 builder.putBlob(new byte[]{5, 124, 118, -1});
756 ByteBuffer b = builder.finish();
757 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
758 byte[] result = r.asBlob().getBytes();
759 TestEq((byte)5, result[0]);
760 TestEq((byte)124, result[1]);
761 TestEq((byte)118, result[2]);
762 TestEq((byte)-1, result[3]);
765 public static void testSingleElementUByte() {
766 FlexBuffersBuilder builder = new FlexBuffersBuilder();
767 builder.putUInt(0xFF);
768 ByteBuffer b = builder.finish();
769 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
770 TestEq(255, (int)r.asUInt());
773 public static void testSingleElementUShort() {
774 FlexBuffersBuilder builder = new FlexBuffersBuilder();
775 builder.putUInt(0xFFFF);
776 ByteBuffer b = builder.finish();
777 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
778 TestEq(65535, (int)r.asUInt());
781 public static void testSingleElementUInt() {
782 FlexBuffersBuilder builder = new FlexBuffersBuilder();
783 builder.putUInt(0xFFFF_FFFFL);
784 ByteBuffer b = builder.finish();
785 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
786 TestEq(4294967295L, r.asUInt());
789 public static void testSingleFixedTypeVector() {
791 int[] ints = new int[]{5, 124, 118, -1};
792 float[] floats = new float[]{5.5f, 124.124f, 118.118f, -1.1f};
793 String[] strings = new String[]{"This", "is", "a", "typed", "array"};
794 boolean[] booleans = new boolean[]{false, true, true, false};
797 FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
798 FlexBuffersBuilder.BUILDER_FLAG_NONE);
800 int mapPos = builder.startMap();
802 int vecPos = builder.startVector();
803 for (final int i : ints) {
806 builder.endVector("ints", vecPos, true, false);
808 vecPos = builder.startVector();
809 for (final float i : floats) {
812 builder.endVector("floats", vecPos, true, false);
814 vecPos = builder.startVector();
815 for (final String i : strings) {
816 builder.putString(i);
818 builder.endVector("strings", vecPos, true, false);
820 vecPos = builder.startVector();
821 for (final boolean i : booleans) {
822 builder.putBoolean(i);
824 builder.endVector("booleans", vecPos, true, false);
826 builder.endMap(null, mapPos);
829 ByteBuffer b = builder.finish();
830 FlexBuffers.Reference r = FlexBuffers.getRoot(b);
831 assert(r.asMap().get("ints").isTypedVector());
832 assert(r.asMap().get("floats").isTypedVector());
833 assert(r.asMap().get("strings").isTypedVector());
834 assert(r.asMap().get("booleans").isTypedVector());
837 public static void testSingleElementVector() {
838 FlexBuffersBuilder b = new FlexBuffersBuilder();
840 int vecPos = b.startVector();
843 int vecpos2 = b.startVector();
846 b.endVector(null, vecpos2, false, false);
847 b.endVector(null, vecPos, false, false);
850 FlexBuffers.Reference r = FlexBuffers.getRoot(b.getBuffer());
851 TestEq(FlexBuffers.FBT_VECTOR, r.getType());
852 FlexBuffers.Vector vec = FlexBuffers.getRoot(b.getBuffer()).asVector();
853 TestEq(3, vec.size());
854 TestEq(99, vec.get(0).asInt());
855 TestEq("wow", vec.get(1).asString());
856 TestEq("[ 99, \"wow\" ]", vec.get(2).toString());
857 TestEq("[ 99, \"wow\", [ 99, \"wow\" ] ]", FlexBuffers.getRoot(b.getBuffer()).toString());
860 public static void testSingleElementMap() {
861 FlexBuffersBuilder b = new FlexBuffersBuilder();
863 int mapPost = b.startMap();
864 b.putInt("myInt", 0x7fffffbbbfffffffL);
865 b.putString("myString", "wow");
866 b.putString("myString2", "incredible");
867 int start = b.startVector();
870 b.endVector("myVec", start, false, false);
872 b.putFloat("double", 0x1.ffffbbbffffffP+1023);
873 b.endMap(null, mapPost);
876 FlexBuffers.Reference r = FlexBuffers.getRoot(b.getBuffer());
877 TestEq(FlexBuffers.FBT_MAP, r.getType());
878 FlexBuffers.Map map = FlexBuffers.getRoot(b.getBuffer()).asMap();
879 TestEq(5, map.size());
880 TestEq(0x7fffffbbbfffffffL, map.get("myInt").asLong());
881 TestEq("wow", map.get("myString").asString());
882 TestEq("incredible", map.get("myString2").asString());
883 TestEq(99, map.get("myVec").asVector().get(0).asInt());
884 TestEq("wow", map.get("myVec").asVector().get(1).asString());
885 TestEq(Double.compare(0x1.ffffbbbffffffP+1023, map.get("double").asFloat()), 0);
886 TestEq("{ \"double\" : 1.7976894783391937E308, \"myInt\" : 9223371743723257855, \"myString\" : \"wow\", \"myString2\" : \"incredible\", \"myVec\" : [ 99, \"wow\" ] }",
887 FlexBuffers.getRoot(b.getBuffer()).toString());
890 public static void testFlexBuferEmpty() {
891 FlexBuffers.Blob blob = FlexBuffers.Blob.empty();
892 FlexBuffers.Map ary = FlexBuffers.Map.empty();
893 FlexBuffers.Vector map = FlexBuffers.Vector.empty();
894 FlexBuffers.TypedVector typedAry = FlexBuffers.TypedVector.empty();
895 TestEq(blob.size(), 0);
896 TestEq(map.size(), 0);
897 TestEq(ary.size(), 0);
898 TestEq(typedAry.size(), 0);
901 public static void testHashMapToMap() {
902 int entriesCount = 12;
904 HashMap<String, String> source = new HashMap<>();
905 for (int i = 0; i < entriesCount; i++) {
906 source.put("foo_param_" + i, "foo_value_" + i);
909 FlexBuffersBuilder builder = new FlexBuffersBuilder(1000);
910 int mapStart = builder.startMap();
911 for (Map.Entry<String, String> entry : source.entrySet()) {
912 builder.putString(entry.getKey(), entry.getValue());
914 builder.endMap(null, mapStart);
915 ByteBuffer bb = builder.finish();
918 FlexBuffers.Reference rootReference = FlexBuffers.getRoot(bb);
920 TestEq(rootReference.isMap(), true);
922 FlexBuffers.Map flexMap = rootReference.asMap();
924 FlexBuffers.KeyVector keys = flexMap.keys();
925 FlexBuffers.Vector values = flexMap.values();
927 TestEq(entriesCount, keys.size());
928 TestEq(entriesCount, values.size());
930 HashMap<String, String> result = new HashMap<>();
931 for (int i = 0; i < keys.size(); i++) {
932 result.put(keys.get(i).toString(), values.get(i).asString());
935 TestEq(source, result);
938 public static void TestFlexBuffers() {
939 testSingleElementByte();
940 testSingleElementShort();
941 testSingleElementInt();
942 testSingleElementLong();
943 testSingleElementFloat();
944 testSingleElementDouble();
945 testSingleElementString();
946 testSingleElementBlob();
947 testSingleElementVector();
948 testSingleFixedTypeVector();
949 testSingleElementUShort();
950 testSingleElementUInt();
951 testSingleElementUByte();
952 testSingleElementMap();
953 testFlexBuffersTest();
955 testFlexBuferEmpty();
958 static <T> void TestEq(T a, T b) {
960 System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
961 System.out.println("FlatBuffers test FAILED: \'" + a + "\' != \'" + b + "\'");
962 new Throwable().printStackTrace();