xref: /aosp_15_r20/external/flatbuffers/tests/JavaTest.java (revision 890232f25432b36107d06881e0a25aaa6b473652)
1 
2 import static com.google.flatbuffers.Constants.*;
3 
4 import DictionaryLookup.*;
5 import MyGame.Example.*;
6 import optional_scalars.ScalarStuff;
7 import optional_scalars.OptionalByte;
8 import MyGame.MonsterExtra;
9 import NamespaceA.*;
10 import NamespaceA.NamespaceB.*;
11 import com.google.flatbuffers.ByteBufferUtil;
12 import com.google.flatbuffers.ByteVector;
13 import com.google.flatbuffers.FlatBufferBuilder;
14 import com.google.flatbuffers.FlexBuffers;
15 import com.google.flatbuffers.FlexBuffersBuilder;
16 import com.google.flatbuffers.StringVector;
17 import com.google.flatbuffers.UnionVector;
18 
19 import com.google.flatbuffers.FlexBuffers.FlexBufferException;
20 import com.google.flatbuffers.FlexBuffers.Reference;
21 import com.google.flatbuffers.FlexBuffers.Vector;
22 import com.google.flatbuffers.ArrayReadWriteBuf;
23 import com.google.flatbuffers.FlexBuffers.KeyVector;
24 
25 import java.io.*;
26 import java.math.BigInteger;
27 import java.nio.ByteBuffer;
28 import java.nio.ByteOrder;
29 import java.nio.CharBuffer;
30 import java.nio.channels.FileChannel;
31 import java.nio.charset.StandardCharsets;
32 import java.util.Arrays;
33 import java.util.HashMap;
34 import java.util.Map;
35 
36 /*
37  * Copyright 2014 Google Inc. All rights reserved.
38  *
39  * Licensed under the Apache License, Version 2.0 (the "License");
40  * you may not use this file except in compliance with the License.
41  * You may obtain a copy of the License at
42  *
43  *     http://www.apache.org/licenses/LICENSE-2.0
44  *
45  * Unless required by applicable law or agreed to in writing, software
46  * distributed under the License is distributed on an "AS IS" BASIS,
47  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48  * See the License for the specific language governing permissions and
49  * limitations under the License.
50  */
51 
52 
53 
54 class JavaTest {
main(String[] args)55     public static void main(String[] args) {
56 
57         // First, let's test reading a FlatBuffer generated by C++ code:
58         // This file was generated from monsterdata_test.json
59 
60         byte[] data = null;
61         File file = new File("monsterdata_test.mon");
62         RandomAccessFile f = null;
63         try {
64             f = new RandomAccessFile(file, "r");
65             data = new byte[(int)f.length()];
66             f.readFully(data);
67             f.close();
68         } catch(java.io.IOException e) {
69             System.out.println("FlatBuffers test: couldn't read file");
70             return;
71         }
72 
73         // Now test it:
74 
75         ByteBuffer bb = ByteBuffer.wrap(data);
76         TestBuffer(bb);
77 
78         // Second, let's create a FlatBuffer from scratch in Java, and test it also.
79         // We use an initial size of 1 to exercise the reallocation algorithm,
80         // normally a size larger than the typical FlatBuffer you generate would be
81         // better for performance.
82         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
83 
84         TestBuilderBasics(fbb, true);
85         TestBuilderBasics(fbb, false);
86 
87         TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
88 
89         TestNamespaceNesting();
90 
91         TestNestedFlatBuffer();
92 
93         TestCreateByteVector();
94 
95         TestCreateUninitializedVector();
96 
97         TestByteBufferFactory();
98 
99         TestSizedInputStream();
100 
101         TestVectorOfUnions();
102 
103         TestFixedLengthArrays();
104 
105         TestFlexBuffers();
106 
107         TestVectorOfBytes();
108 
109         TestSharedStringPool();
110 
111         TestScalarOptional();
112 
113         TestPackUnpack(bb);
114 
115         TestDictionaryLookup();
116 
117         System.out.println("FlatBuffers test: completed successfully");
118     }
119 
TestEnums()120     static void TestEnums() {
121       TestEq(Color.name(Color.Red), "Red");
122       TestEq(Color.name(Color.Blue), "Blue");
123       TestEq(Any.name(Any.NONE), "NONE");
124       TestEq(Any.name(Any.Monster), "Monster");
125     }
126 
TestBuffer(ByteBuffer bb)127     static void TestBuffer(ByteBuffer bb) {
128         TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
129 
130         Monster monster = Monster.getRootAsMonster(bb);
131 
132         TestEq(monster.hp(), (short)80);
133         TestEq(monster.mana(), (short)150);  // default
134 
135         TestEq(monster.name(), "MyMonster");
136         // monster.friendly() // can't access, deprecated
137 
138         Vec3 pos = monster.pos();
139         TestEq(pos.x(), 1.0f);
140         TestEq(pos.y(), 2.0f);
141         TestEq(pos.z(), 3.0f);
142         TestEq(pos.test1(), 3.0);
143         // issue: int != byte
144         TestEq(pos.test2(), (int) Color.Green);
145         Test t = pos.test3();
146         TestEq(t.a(), (short)5);
147         TestEq(t.b(), (byte)6);
148 
149         TestEq(monster.testType(), (byte)Any.Monster);
150         Monster monster2 = new Monster();
151         TestEq(monster.test(monster2) != null, true);
152         TestEq(monster2.name(), "Fred");
153 
154         TestEq(monster.inventoryLength(), 5);
155         int invsum = 0;
156         for (int i = 0; i < monster.inventoryLength(); i++)
157             invsum += monster.inventory(i);
158         TestEq(invsum, 10);
159 
160         // Method using a vector access object:
161         ByteVector inventoryVector = monster.inventoryVector();
162         TestEq(inventoryVector.length(), 5);
163         invsum = 0;
164         for (int i = 0; i < inventoryVector.length(); i++)
165             invsum += inventoryVector.getAsUnsigned(i);
166         TestEq(invsum, 10);
167 
168         // Alternative way of accessing a vector:
169         ByteBuffer ibb = monster.inventoryAsByteBuffer();
170         invsum = 0;
171         while (ibb.position() < ibb.limit())
172             invsum += ibb.get();
173         TestEq(invsum, 10);
174 
175         Test test_0 = monster.test4(0);
176         Test test_1 = monster.test4(1);
177         TestEq(monster.test4Length(), 2);
178         TestEq(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
179 
180         Test.Vector test4Vector = monster.test4Vector();
181         test_0 = test4Vector.get(0);
182         test_1 = test4Vector.get(1);
183         TestEq(test4Vector.length(), 2);
184         TestEq(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
185 
186         TestEq(monster.testarrayofstringLength(), 2);
187         TestEq(monster.testarrayofstring(0),"test1");
188         TestEq(monster.testarrayofstring(1),"test2");
189 
190         // Method using a vector access object:
191         StringVector testarrayofstringVector = monster.testarrayofstringVector();
192         TestEq(testarrayofstringVector.length(), 2);
193         TestEq(testarrayofstringVector.get(0),"test1");
194         TestEq(testarrayofstringVector.get(1),"test2");
195 
196         TestEq(monster.testbool(), true);
197     }
198 
199     // this method checks additional fields not present in the binary buffer read from file
200     // these new tests are performed on top of the regular tests
TestExtendedBuffer(ByteBuffer bb)201     static void TestExtendedBuffer(ByteBuffer bb) {
202         TestBuffer(bb);
203 
204         Monster monster = Monster.getRootAsMonster(bb);
205 
206         TestEq(monster.testhashu32Fnv1(), Integer.MAX_VALUE + 1L);
207     }
208 
TestNamespaceNesting()209     static void TestNamespaceNesting() {
210         // reference / manipulate these to verify compilation
211         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
212 
213         TableInNestedNS.startTableInNestedNS(fbb);
214         TableInNestedNS.addFoo(fbb, 1234);
215         int nestedTableOff = TableInNestedNS.endTableInNestedNS(fbb);
216 
217         TableInFirstNS.startTableInFirstNS(fbb);
218         TableInFirstNS.addFooTable(fbb, nestedTableOff);
219         int off = TableInFirstNS.endTableInFirstNS(fbb);
220     }
221 
TestNestedFlatBuffer()222     static void TestNestedFlatBuffer() {
223         final String nestedMonsterName = "NestedMonsterName";
224         final short nestedMonsterHp = 600;
225         final short nestedMonsterMana = 1024;
226 
227         FlatBufferBuilder fbb1 = new FlatBufferBuilder(16);
228         int str1 = fbb1.createString(nestedMonsterName);
229         Monster.startMonster(fbb1);
230         Monster.addName(fbb1, str1);
231         Monster.addHp(fbb1, nestedMonsterHp);
232         Monster.addMana(fbb1, nestedMonsterMana);
233         int monster1 = Monster.endMonster(fbb1);
234         Monster.finishMonsterBuffer(fbb1, monster1);
235         byte[] fbb1Bytes = fbb1.sizedByteArray();
236         fbb1 = null;
237 
238         FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
239         int str2 = fbb2.createString("My Monster");
240         int nestedBuffer = Monster.createTestnestedflatbufferVector(fbb2, fbb1Bytes);
241         Monster.startMonster(fbb2);
242         Monster.addName(fbb2, str2);
243         Monster.addHp(fbb2, (short)50);
244         Monster.addMana(fbb2, (short)32);
245         Monster.addTestnestedflatbuffer(fbb2, nestedBuffer);
246         int monster = Monster.endMonster(fbb2);
247         Monster.finishMonsterBuffer(fbb2, monster);
248 
249         // Now test the data extracted from the nested buffer
250         Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
251         Monster nestedMonster = mons.testnestedflatbufferAsMonster();
252 
253         TestEq(nestedMonsterMana, nestedMonster.mana());
254         TestEq(nestedMonsterHp, nestedMonster.hp());
255         TestEq(nestedMonsterName, nestedMonster.name());
256     }
257 
TestCreateByteVector()258     static void TestCreateByteVector() {
259         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
260         int str = fbb.createString("MyMonster");
261         byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
262         int vec = fbb.createByteVector(inventory);
263         Monster.startMonster(fbb);
264         Monster.addInventory(fbb, vec);
265         Monster.addName(fbb, str);
266         int monster1 = Monster.endMonster(fbb);
267         Monster.finishMonsterBuffer(fbb, monster1);
268         Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
269 
270         TestEq(monsterObject.inventory(1), (int)inventory[1]);
271         TestEq(monsterObject.inventoryLength(), inventory.length);
272         ByteVector inventoryVector = monsterObject.inventoryVector();
273         TestEq(inventoryVector.getAsUnsigned(1), (int)inventory[1]);
274         TestEq(inventoryVector.length(), inventory.length);
275 
276         TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
277     }
278 
TestCreateUninitializedVector()279     static void TestCreateUninitializedVector() {
280         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
281         int str = fbb.createString("MyMonster");
282         byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
283         ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
284         for (byte i:inventory) {
285             bb.put(i);
286         }
287         int vec = fbb.endVector();
288         Monster.startMonster(fbb);
289         Monster.addInventory(fbb, vec);
290         Monster.addName(fbb, str);
291         int monster1 = Monster.endMonster(fbb);
292         Monster.finishMonsterBuffer(fbb, monster1);
293         Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
294 
295         TestEq(monsterObject.inventory(1), (int)inventory[1]);
296         TestEq(monsterObject.inventoryLength(), inventory.length);
297         ByteVector inventoryVector = monsterObject.inventoryVector();
298         TestEq(inventoryVector.getAsUnsigned(1), (int)inventory[1]);
299         TestEq(inventoryVector.length(), inventory.length);
300         TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
301     }
302 
TestByteBufferFactory()303     static void TestByteBufferFactory() {
304         final class MappedByteBufferFactory extends FlatBufferBuilder.ByteBufferFactory {
305             @Override
306             public ByteBuffer newByteBuffer(int capacity) {
307                 ByteBuffer bb;
308                 try {
309                     RandomAccessFile f = new RandomAccessFile("javatest.bin", "rw");
310                     bb =  f.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, capacity).order(ByteOrder.LITTLE_ENDIAN);
311                     f.close();
312                 } catch(Throwable e) {
313                     System.out.println("FlatBuffers test: couldn't map ByteBuffer to a file");
314                     bb = null;
315                 }
316                 return bb;
317             }
318         }
319 
320         FlatBufferBuilder fbb = new FlatBufferBuilder(1, new MappedByteBufferFactory());
321 
322         TestBuilderBasics(fbb, false);
323     }
324 
TestSizedInputStream()325     static void TestSizedInputStream() {
326         // Test on default FlatBufferBuilder that uses HeapByteBuffer
327         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
328 
329         TestBuilderBasics(fbb, false);
330 
331         InputStream in = fbb.sizedInputStream();
332         byte[] array = fbb.sizedByteArray();
333         int count = 0;
334         int currentVal = 0;
335 
336         while (currentVal != -1 && count < array.length) {
337             try {
338                 currentVal = in.read();
339             } catch(java.io.IOException e) {
340                 System.out.println("FlatBuffers test: couldn't read from InputStream");
341                 return;
342             }
343             TestEq((byte)currentVal, array[count]);
344             count++;
345         }
346         TestEq(count, array.length);
347     }
348 
TestBuilderBasics(FlatBufferBuilder fbb, boolean sizePrefix)349     static void TestBuilderBasics(FlatBufferBuilder fbb, boolean sizePrefix) {
350         int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
351         int[] off = new int[3];
352         Monster.startMonster(fbb);
353         Monster.addName(fbb, names[0]);
354         off[0] = Monster.endMonster(fbb);
355         Monster.startMonster(fbb);
356         Monster.addName(fbb, names[1]);
357         off[1] = Monster.endMonster(fbb);
358         Monster.startMonster(fbb);
359         Monster.addName(fbb, names[2]);
360         off[2] = Monster.endMonster(fbb);
361         int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
362 
363         // We set up the same values as monsterdata.json:
364 
365         int str = fbb.createString("MyMonster");
366 
367         int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
368 
369         int fred = fbb.createString("Fred");
370         Monster.startMonster(fbb);
371         Monster.addName(fbb, fred);
372         int mon2 = Monster.endMonster(fbb);
373 
374         Monster.startTest4Vector(fbb, 2);
375         Test.createTest(fbb, (short)10, (byte)20);
376         Test.createTest(fbb, (short)30, (byte)40);
377         int test4 = fbb.endVector();
378 
379         int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
380                 fbb.createString("test1"),
381                 fbb.createString("test2")
382         });
383 
384         Monster.startMonster(fbb);
385         Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
386                 Color.Green, (short)5, (byte)6));
387         Monster.addHp(fbb, (short)80);
388         Monster.addName(fbb, str);
389         Monster.addInventory(fbb, inv);
390         Monster.addTestType(fbb, (byte)Any.Monster);
391         Monster.addTest(fbb, mon2);
392         Monster.addTest4(fbb, test4);
393         Monster.addTestarrayofstring(fbb, testArrayOfString);
394         Monster.addTestbool(fbb, true);
395         Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
396         Monster.addTestarrayoftables(fbb, sortMons);
397         int mon = Monster.endMonster(fbb);
398 
399         if (sizePrefix) {
400             Monster.finishSizePrefixedMonsterBuffer(fbb, mon);
401         } else {
402             Monster.finishMonsterBuffer(fbb, mon);
403         }
404 
405         // Write the result to a file for debugging purposes:
406         // Note that the binaries are not necessarily identical, since the JSON
407         // parser may serialize in a slightly different order than the above
408         // Java code. They are functionally equivalent though.
409 
410         try {
411             String filename = "monsterdata_java_wire" + (sizePrefix ? "_sp" : "") + ".mon";
412             FileChannel fc = new FileOutputStream(filename).getChannel();
413             fc.write(fbb.dataBuffer().duplicate());
414             fc.close();
415         } catch(java.io.IOException e) {
416             System.out.println("FlatBuffers test: couldn't write file");
417             return;
418         }
419 
420         // Test it:
421         ByteBuffer dataBuffer = fbb.dataBuffer();
422         if (sizePrefix) {
423             TestEq(ByteBufferUtil.getSizePrefix(dataBuffer) + SIZE_PREFIX_LENGTH,
424                    dataBuffer.remaining());
425             dataBuffer = ByteBufferUtil.removeSizePrefix(dataBuffer);
426         }
427         TestExtendedBuffer(dataBuffer);
428 
429         // Make sure it also works with read only ByteBuffers. This is slower,
430         // since creating strings incurs an additional copy
431         // (see Table.__string).
432         TestExtendedBuffer(dataBuffer.asReadOnlyBuffer());
433 
434         TestEnums();
435 
436         //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
437         // revert to original values after testing
438         Monster monster = Monster.getRootAsMonster(dataBuffer);
439 
440         // mana is optional and does not exist in the buffer so the mutation should fail
441         // the mana field should retain its default value
442         TestEq(monster.mutateMana((short)10), false);
443         TestEq(monster.mana(), (short)150);
444 
445         // Accessing a vector of sorted by the key tables
446         TestEq(monster.testarrayoftables(0).name(), "Barney");
447         TestEq(monster.testarrayoftables(1).name(), "Frodo");
448         TestEq(monster.testarrayoftables(2).name(), "Wilma");
449         Monster.Vector testarrayoftablesVector = monster.testarrayoftablesVector();
450         TestEq(testarrayoftablesVector.get(0).name(), "Barney");
451         TestEq(testarrayoftablesVector.get(1).name(), "Frodo");
452         TestEq(testarrayoftablesVector.get(2).name(), "Wilma");
453 
454         // Example of searching for a table by the key
455         TestEq(monster.testarrayoftablesByKey("Frodo").name(), "Frodo");
456         TestEq(monster.testarrayoftablesByKey("Barney").name(), "Barney");
457         TestEq(monster.testarrayoftablesByKey("Wilma").name(), "Wilma");
458         TestEq(testarrayoftablesVector.getByKey("Frodo").name(), "Frodo");
459         TestEq(testarrayoftablesVector.getByKey("Barney").name(), "Barney");
460         TestEq(testarrayoftablesVector.getByKey("Wilma").name(), "Wilma");
461 
462         // testType is an existing field and mutating it should succeed
463         TestEq(monster.testType(), (byte)Any.Monster);
464 
465         //mutate the inventory vector
466         TestEq(monster.mutateInventory(0, 1), true);
467         TestEq(monster.mutateInventory(1, 2), true);
468         TestEq(monster.mutateInventory(2, 3), true);
469         TestEq(monster.mutateInventory(3, 4), true);
470         TestEq(monster.mutateInventory(4, 5), true);
471 
472         for (int i = 0; i < monster.inventoryLength(); i++) {
473             TestEq(monster.inventory(i), i + 1);
474         }
475         ByteVector inventoryVector =  monster.inventoryVector();
476         for (int i = 0; i < inventoryVector.length(); i++) {
477             TestEq((int)inventoryVector.get(i), i + 1);
478         }
479 
480         //reverse mutation
481         TestEq(monster.mutateInventory(0, 0), true);
482         TestEq(monster.mutateInventory(1, 1), true);
483         TestEq(monster.mutateInventory(2, 2), true);
484         TestEq(monster.mutateInventory(3, 3), true);
485         TestEq(monster.mutateInventory(4, 4), true);
486 
487         // get a struct field and edit one of its fields
488         Vec3 pos = monster.pos();
489         TestEq(pos.x(), 1.0f);
490         pos.mutateX(55.0f);
491         TestEq(pos.x(), 55.0f);
492         pos.mutateX(1.0f);
493         TestEq(pos.x(), 1.0f);
494     }
495 
TestVectorOfUnions()496     static void TestVectorOfUnions() {
497         final FlatBufferBuilder fbb = new FlatBufferBuilder();
498 
499         final int swordAttackDamage = 1;
500 
501         final int[] characterVector = new int[] {
502             Attacker.createAttacker(fbb, swordAttackDamage),
503         };
504 
505         final byte[] characterTypeVector = new byte[]{
506             Character.MuLan,
507         };
508 
509         Movie.finishMovieBuffer(
510             fbb,
511             Movie.createMovie(
512                 fbb,
513                 (byte)0,
514                 (byte)0,
515                 Movie.createCharactersTypeVector(fbb, characterTypeVector),
516                 Movie.createCharactersVector(fbb, characterVector)
517             )
518         );
519 
520         final Movie movie = Movie.getRootAsMovie(fbb.dataBuffer());
521         ByteVector charactersTypeByteVector = movie.charactersTypeVector();
522         UnionVector charactersVector = movie.charactersVector();
523 
524         TestEq(movie.charactersTypeLength(), characterTypeVector.length);
525         TestEq(charactersTypeByteVector.length(), characterTypeVector.length);
526         TestEq(movie.charactersLength(), characterVector.length);
527         TestEq(charactersVector.length(), characterVector.length);
528 
529         TestEq(movie.charactersType(0), characterTypeVector[0]);
530         TestEq(charactersTypeByteVector.get(0), characterTypeVector[0]);
531 
532         TestEq(((Attacker)movie.characters(new Attacker(), 0)).swordAttackDamage(), swordAttackDamage);
533     }
534 
TestFixedLengthArrays()535     static void TestFixedLengthArrays() {
536         FlatBufferBuilder builder = new FlatBufferBuilder(0);
537 
538         float       a;
539         int[]       b = new int[15];
540         byte        c;
541         int[][]     d_a = new int[2][2];
542         byte[]      d_b = new byte[2];
543         byte[][]    d_c = new byte[2][2];
544         long[][]    d_d = new long[2][2];
545         int         e;
546         long[]      f = new long[2];
547 
548         a = 0.5f;
549         for (int i = 0; i < 15; i++) b[i] = i;
550         c = 1;
551         d_a[0][0] = 1;
552         d_a[0][1] = 2;
553         d_a[1][0] = 3;
554         d_a[1][1] = 4;
555         d_b[0] = TestEnum.B;
556         d_b[1] = TestEnum.C;
557         d_c[0][0] = TestEnum.A;
558         d_c[0][1] = TestEnum.B;
559         d_c[1][0] = TestEnum.C;
560         d_c[1][1] = TestEnum.B;
561         d_d[0][0] = -1;
562         d_d[0][1] = 1;
563         d_d[1][0] = -2;
564         d_d[1][1] = 2;
565         e = 2;
566         f[0] = -1;
567         f[1] = 1;
568 
569         int arrayOffset = ArrayStruct.createArrayStruct(builder,
570             a, b, c, d_a, d_b, d_c, d_d, e, f);
571 
572         // Create a table with the ArrayStruct.
573         ArrayTable.startArrayTable(builder);
574         ArrayTable.addA(builder, arrayOffset);
575         int tableOffset = ArrayTable.endArrayTable(builder);
576 
577         ArrayTable.finishArrayTableBuffer(builder, tableOffset);
578 
579         ArrayTable table = ArrayTable.getRootAsArrayTable(builder.dataBuffer());
580         NestedStruct nested = new NestedStruct();
581 
582         TestEq(table.a().a(), 0.5f);
583         for (int i = 0; i < 15; i++) TestEq(table.a().b(i), i);
584         TestEq(table.a().c(), (byte)1);
585         TestEq(table.a().d(nested, 0).a(0), 1);
586         TestEq(table.a().d(nested, 0).a(1), 2);
587         TestEq(table.a().d(nested, 1).a(0), 3);
588         TestEq(table.a().d(nested, 1).a(1), 4);
589         TestEq(table.a().d(nested, 0).b(), TestEnum.B);
590         TestEq(table.a().d(nested, 1).b(), TestEnum.C);
591         TestEq(table.a().d(nested, 0).c(0), TestEnum.A);
592         TestEq(table.a().d(nested, 0).c(1), TestEnum.B);
593         TestEq(table.a().d(nested, 1).c(0), TestEnum.C);
594         TestEq(table.a().d(nested, 1).c(1), TestEnum.B);
595         TestEq(table.a().d(nested, 0).d(0), (long)-1);
596         TestEq(table.a().d(nested, 0).d(1), (long)1);
597         TestEq(table.a().d(nested, 1).d(0), (long)-2);
598         TestEq(table.a().d(nested, 1).d(1), (long)2);
599         TestEq(table.a().e(), 2);
600         TestEq(table.a().f(0), (long)-1);
601         TestEq(table.a().f(1), (long)1);
602     }
603 
testFlexBuffersTest()604     public static void testFlexBuffersTest() {
605         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
606                 FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
607         testFlexBuffersTest(builder);
608         int bufferLimit1 = ((ArrayReadWriteBuf) builder.getBuffer()).limit();
609 
610         // Repeat after clearing the builder to ensure the builder is reusable
611         builder.clear();
612         testFlexBuffersTest(builder);
613         int bufferLimit2 = ((ArrayReadWriteBuf) builder.getBuffer()).limit();
614         TestEq(bufferLimit1, bufferLimit2);
615     }
616 
testFlexBuffersTest(FlexBuffersBuilder builder)617     public static void testFlexBuffersTest(FlexBuffersBuilder builder) {
618         // Write the equivalent of:
619         // { vec: [ -100, "Fred", 4.0, false ], bar: [ 1, 2, 3 ], bar3: [ 1, 2, 3 ],
620         // foo: 100, bool: true, mymap: { foo: "Fred" } }
621         // It's possible to do this without std::function support as well.
622         int map1 = builder.startMap();
623 
624         int vec1 = builder.startVector();
625         builder.putInt(-100);
626         builder.putString("Fred");
627         builder.putBlob(new byte[]{(byte) 77});
628         builder.putBoolean(false);
629         builder.putInt(Long.MAX_VALUE);
630 
631         int map2 = builder.startMap();
632         builder.putInt("test", 200);
633         builder.endMap(null, map2);
634 
635         builder.putFloat(150.9);
636         builder.putFloat(150.9999998);
637         builder.endVector("vec", vec1, false, false);
638 
639         vec1 = builder.startVector();
640         builder.putInt(1);
641         builder.putInt(2);
642         builder.putInt(3);
643         builder.endVector("bar", vec1, true, false);
644 
645         vec1 = builder.startVector();
646         builder.putBoolean(true);
647         builder.putBoolean(false);
648         builder.putBoolean(true);
649         builder.putBoolean(false);
650         builder.endVector("bools", vec1, true, false);
651 
652         builder.putBoolean("bool", true);
653         builder.putFloat("foo", 100);
654 
655         map2 = builder.startMap();
656         builder.putString("bar", "Fred");  // Testing key and string reuse.
657         builder.putInt("int", -120);
658         builder.putFloat("float", -123.0f);
659         builder.putBlob("blob", new byte[]{ 65, 67 });
660         builder.endMap("mymap", map2);
661 
662         builder.endMap(null, map1);
663         builder.finish();
664 
665         FlexBuffers.Map m = FlexBuffers.getRoot(builder.getBuffer()).asMap();
666 
667         TestEq(m.size(), 6);
668 
669         // test empty (an null)
670         TestEq(m.get("no_key").asString(), ""); // empty if fail
671         TestEq(m.get("no_key").asMap(), FlexBuffers.Map.empty()); // empty if fail
672         TestEq(m.get("no_key").asKey(), FlexBuffers.Key.empty()); // empty if fail
673         TestEq(m.get("no_key").asVector(), FlexBuffers.Vector.empty()); // empty if fail
674         TestEq(m.get("no_key").asBlob(), FlexBuffers.Blob.empty()); // empty if fail
675         assert(m.get("no_key").asVector().isEmpty()); // empty if fail
676 
677         // testing "vec" field
678         FlexBuffers.Vector vec = m.get("vec").asVector();
679         TestEq(vec.size(), 8);
680         TestEq(vec.get(0).asLong(), (long) -100);
681         TestEq(vec.get(1).asString(), "Fred");
682         TestEq(vec.get(2).isBlob(), true);
683         TestEq(vec.get(2).asBlob().size(), 1);
684         TestEq(vec.get(2).asBlob().data().get(0), (byte) 77);
685         TestEq(vec.get(3).isBoolean(), true);   // Check if type is a bool
686         TestEq(vec.get(3).asBoolean(), false);  // Check if value is false
687         TestEq(vec.get(4).asLong(), Long.MAX_VALUE);
688         TestEq(vec.get(5).isMap(), true);
689         TestEq(vec.get(5).asMap().get("test").asInt(), 200);
690         TestEq(Float.compare((float)vec.get(6).asFloat(), 150.9f), 0);
691         TestEq(Double.compare(vec.get(7).asFloat(), 150.9999998), 0);
692         TestEq((long)0, (long)vec.get(1).asLong()); //conversion fail returns 0 as C++
693 
694         // bar vector
695         FlexBuffers.Vector tvec = m.get("bar").asVector();
696         TestEq(tvec.size(), 3);
697         TestEq(tvec.get(0).asInt(), 1);
698         TestEq(tvec.get(1).asInt(), 2);
699         TestEq(tvec.get(2).asInt(), 3);
700         TestEq(((FlexBuffers.TypedVector) tvec).getElemType(), FlexBuffers.FBT_INT);
701 
702         // bools vector
703         FlexBuffers.Vector bvec = m.get("bools").asVector();
704         TestEq(bvec.size(), 4);
705         TestEq(bvec.get(0).asBoolean(), true);
706         TestEq(bvec.get(1).asBoolean(), false);
707         TestEq(bvec.get(2).asBoolean(), true);
708         TestEq(bvec.get(3).asBoolean(), false);
709         TestEq(((FlexBuffers.TypedVector) bvec).getElemType(), FlexBuffers.FBT_BOOL);
710 
711 
712         TestEq((float)m.get("foo").asFloat(), (float) 100);
713         TestEq(m.get("unknown").isNull(), true);
714 
715         // mymap vector
716         FlexBuffers.Map mymap = m.get("mymap").asMap();
717         TestEq(mymap.keys().get(0), m.keys().get(0)); // These should be equal by pointer equality, since key and value are shared.
718         TestEq(mymap.keys().get(0).toString(), "bar");
719         TestEq(mymap.values().get(0).asString(), vec.get(1).asString());
720         TestEq(mymap.get("int").asInt(), -120);
721         TestEq((float)mymap.get("float").asFloat(), -123.0f);
722         TestEq(Arrays.equals(mymap.get("blob").asBlob().getBytes(), new byte[]{ 65, 67 }), true);
723         TestEq(mymap.get("blob").asBlob().toString(), "AC");
724         TestEq(mymap.get("blob").toString(), "\"AC\"");
725     }
726 
testFlexBufferVectorStrings()727     public static void testFlexBufferVectorStrings() {
728         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(10000000));
729 
730         int size = 3000;
731         StringBuilder sb = new StringBuilder();
732         for (int i=0; i< size; i++) {
733             sb.append("a");
734         }
735 
736         String text = sb.toString();
737         TestEq(text.length(), size);
738 
739         int pos = builder.startVector();
740 
741         for (int i=0; i<size; i++) {
742             builder.putString(text);
743         }
744 
745         try {
746             builder.endVector(null, pos, true, false);
747             // this should raise an exception as
748             // typed vector of string was deprecated
749             assert false;
750         } catch(FlexBufferException fb) {
751             // no op
752         }
753         // we finish the vector again as non-typed
754         builder.endVector(null, pos, false, false);
755 
756         ByteBuffer b = builder.finish();
757         Vector v = FlexBuffers.getRoot(b).asVector();
758 
759         TestEq(v.size(), size);
760         for (int i=0; i<size; i++) {
761             TestEq(v.get(i).asString().length(), size);
762             TestEq(v.get(i).asString(), text);
763         }
764     }
765 
testDeprecatedTypedVectorString()766     public static void testDeprecatedTypedVectorString() {
767         // tests whether we are able to support reading deprecated typed vector string
768         // data is equivalent to [ "abc", "abc", "abc", "abc"]
769         byte[] data = new byte[] {0x03, 0x61, 0x62, 0x63, 0x00, 0x03, 0x61, 0x62, 0x63, 0x00,
770             0x03, 0x61, 0x62, 0x63, 0x00, 0x03, 0x61, 0x62, 0x63, 0x00, 0x04, 0x14, 0x10,
771              0x0c, 0x08, 0x04, 0x3c, 0x01};
772         Reference ref = FlexBuffers.getRoot(ByteBuffer.wrap(data));
773         TestEq(ref.getType(), FlexBuffers.FBT_VECTOR_STRING_DEPRECATED);
774         TestEq(ref.isTypedVector(), true);
775         Vector vec = ref.asVector();
776         for (int i=0; i< vec.size(); i++) {
777             TestEq("abc", vec.get(i).asString());
778         }
779     }
780 
testSingleElementBoolean()781     public static void testSingleElementBoolean() {
782         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(100));
783         builder.putBoolean(true);
784         ByteBuffer b = builder.finish();
785         assert(FlexBuffers.getRoot(b).asBoolean());
786     }
787 
testSingleElementByte()788     public static void testSingleElementByte() {
789         FlexBuffersBuilder builder = new FlexBuffersBuilder();
790         builder.putInt(10);
791         ByteBuffer b = builder.finish();
792         TestEq(10, FlexBuffers.getRoot(b).asInt());
793     }
794 
testSingleElementShort()795     public static void testSingleElementShort() {
796         FlexBuffersBuilder builder = new FlexBuffersBuilder();
797         builder.putInt(Short.MAX_VALUE);
798         ByteBuffer b = builder.finish();
799         TestEq(Short.MAX_VALUE, (short)FlexBuffers.getRoot(b).asInt());
800     }
801 
testSingleElementInt()802     public static void testSingleElementInt() {
803         FlexBuffersBuilder builder = new FlexBuffersBuilder();
804         builder.putInt(Integer.MIN_VALUE);
805         ByteBuffer b = builder.finish();
806         TestEq(Integer.MIN_VALUE, FlexBuffers.getRoot(b).asInt());
807     }
808 
testSingleElementLong()809     public static void testSingleElementLong() {
810         FlexBuffersBuilder builder = new FlexBuffersBuilder();
811         builder.putInt(Long.MAX_VALUE);
812         ByteBuffer b = builder.finish();
813         TestEq(Long.MAX_VALUE, FlexBuffers.getRoot(b).asLong());
814     }
815 
testSingleElementFloat()816     public static void testSingleElementFloat() {
817         FlexBuffersBuilder builder = new FlexBuffersBuilder();
818         builder.putFloat(Float.MAX_VALUE);
819         ByteBuffer b = builder.finish();
820         TestEq(Float.compare(Float.MAX_VALUE, (float) FlexBuffers.getRoot(b).asFloat()), 0);
821     }
822 
testSingleElementDouble()823     public static void testSingleElementDouble() {
824         FlexBuffersBuilder builder = new FlexBuffersBuilder();
825         builder.putFloat(Double.MAX_VALUE);
826         ByteBuffer b = builder.finish();
827         TestEq(Double.compare(Double.MAX_VALUE, FlexBuffers.getRoot(b).asFloat()), 0);
828     }
829 
testSingleElementBigString()830     public static void testSingleElementBigString() {
831         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(10000));
832         StringBuilder sb = new StringBuilder();
833 
834         for (int i=0; i< 3000; i++) {
835             sb.append("a");
836         }
837 
838         builder.putString(sb.toString());
839         ByteBuffer b = builder.finish();
840 
841         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
842 
843         TestEq(FlexBuffers.FBT_STRING, r.getType());
844         TestEq(sb.toString(), r.asString());
845     }
846 
testSingleElementSmallString()847     public static void testSingleElementSmallString() {
848         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(10000));
849 
850         builder.putString("aa");
851         ByteBuffer b = builder.finish();
852         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
853 
854         TestEq(FlexBuffers.FBT_STRING, r.getType());
855         TestEq("aa", r.asString());
856     }
857 
testSingleElementBlob()858     public static void testSingleElementBlob() {
859         FlexBuffersBuilder builder = new FlexBuffersBuilder();
860         builder.putBlob(new byte[]{5, 124, 118, -1});
861         ByteBuffer b = builder.finish();
862         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
863         byte[] result = r.asBlob().getBytes();
864         TestEq((byte)5, result[0]);
865         TestEq((byte)124, result[1]);
866         TestEq((byte)118, result[2]);
867         TestEq((byte)-1, result[3]);
868     }
869 
testSingleElementLongBlob()870     public static void testSingleElementLongBlob() {
871 
872         // verifies blobs of up to 2^16 in length
873         for (int i = 2; i <= 1<<16; i = i<<1) {
874             byte[] input = new byte[i-1];
875             for (int index = 0; index < input.length; index++) {
876                 input[index] = (byte)(index % 64);
877             }
878 
879             FlexBuffersBuilder builder = new FlexBuffersBuilder();
880             builder.putBlob(input);
881             ByteBuffer b = builder.finish();
882             FlexBuffers.Reference r = FlexBuffers.getRoot(b);
883             byte[] result = r.asBlob().getBytes();
884 
885             for (int index = 0; index < input.length; index++) {
886                 TestEq((byte)(index % 64), result[index]);
887             }
888         }
889     }
890 
testSingleElementUByte()891     public static void testSingleElementUByte() {
892         FlexBuffersBuilder builder = new FlexBuffersBuilder();
893         builder.putUInt(0xFF);
894         ByteBuffer b = builder.finish();
895         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
896         TestEq(255, (int)r.asUInt());
897     }
898 
testSingleElementUShort()899     public static void testSingleElementUShort() {
900         FlexBuffersBuilder builder = new FlexBuffersBuilder();
901         builder.putUInt(0xFFFF);
902         ByteBuffer b = builder.finish();
903         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
904         TestEq(65535, (int)r.asUInt());
905     }
906 
testSingleElementUInt()907     public static void testSingleElementUInt() {
908         FlexBuffersBuilder builder = new FlexBuffersBuilder();
909         builder.putUInt(0xFFFF_FFFFL);
910         ByteBuffer b = builder.finish();
911         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
912         TestEq(4294967295L, r.asUInt());
913     }
914 
testSingleFixedTypeVector()915     public static void testSingleFixedTypeVector() {
916 
917         int[] ints = new int[]{5, 124, 118, -1};
918         float[] floats = new float[]{5.5f, 124.124f, 118.118f, -1.1f};
919         String[] strings = new String[]{"This", "is", "a", "typed", "array"};
920         boolean[] booleans = new boolean[]{false, true, true, false};
921 
922 
923         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
924                 FlexBuffersBuilder.BUILDER_FLAG_NONE);
925 
926         int mapPos = builder.startMap();
927 
928         int vecPos = builder.startVector();
929         for (final int i : ints) {
930             builder.putInt(i);
931         }
932         builder.endVector("ints", vecPos, true, false);
933 
934         vecPos = builder.startVector();
935         for (final float i : floats) {
936             builder.putFloat(i);
937         }
938         builder.endVector("floats", vecPos, true, false);
939 
940         vecPos = builder.startVector();
941         for (final boolean i : booleans) {
942             builder.putBoolean(i);
943         }
944         builder.endVector("booleans", vecPos, true, false);
945 
946         builder.endMap(null, mapPos);
947 
948 
949         ByteBuffer b = builder.finish();
950         FlexBuffers.Reference r = FlexBuffers.getRoot(b);
951         assert(r.asMap().get("ints").isTypedVector());
952         assert(r.asMap().get("floats").isTypedVector());
953         assert(r.asMap().get("booleans").isTypedVector());
954     }
955 
testSingleElementVector()956     public static void testSingleElementVector() {
957         FlexBuffersBuilder b = new FlexBuffersBuilder();
958 
959         int vecPos = b.startVector();
960         b.putInt(99);
961         b.putString("wow");
962         int vecpos2 = b.startVector();
963         b.putInt(99);
964         b.putString("wow");
965         b.endVector(null, vecpos2, false, false);
966         b.endVector(null, vecPos, false, false);
967         b.finish();
968 
969         FlexBuffers.Reference r = FlexBuffers.getRoot(b.getBuffer());
970         TestEq(FlexBuffers.FBT_VECTOR, r.getType());
971         FlexBuffers.Vector vec = FlexBuffers.getRoot(b.getBuffer()).asVector();
972         TestEq(3, vec.size());
973         TestEq(99, vec.get(0).asInt());
974         TestEq("wow", vec.get(1).asString());
975         TestEq("[ 99, \"wow\" ]", vec.get(2).toString());
976         TestEq("[ 99, \"wow\", [ 99, \"wow\" ] ]", FlexBuffers.getRoot(b.getBuffer()).toString());
977     }
978 
testSingleElementMap()979     public static void testSingleElementMap() {
980         FlexBuffersBuilder b = new FlexBuffersBuilder();
981 
982         int mapPost = b.startMap();
983         b.putInt("myInt", 0x7fffffbbbfffffffL);
984         b.putString("myString", "wow");
985         b.putString("myString2", "incredible");
986         int start = b.startVector();
987         b.putInt(99);
988         b.putString("wow");
989         b.endVector("myVec", start, false, false);
990 
991         b.putFloat("double", 0x1.ffffbbbffffffP+1023);
992         b.endMap(null, mapPost);
993         b.finish();
994 
995         FlexBuffers.Reference r = FlexBuffers.getRoot(b.getBuffer());
996         TestEq(FlexBuffers.FBT_MAP, r.getType());
997         FlexBuffers.Map map = FlexBuffers.getRoot(b.getBuffer()).asMap();
998         TestEq(5, map.size());
999         TestEq(0x7fffffbbbfffffffL, map.get("myInt").asLong());
1000         TestEq("wow", map.get("myString").asString());
1001         TestEq("incredible", map.get("myString2").asString());
1002         TestEq(99, map.get("myVec").asVector().get(0).asInt());
1003         TestEq("wow", map.get("myVec").asVector().get(1).asString());
1004         TestEq(Double.compare(0x1.ffffbbbffffffP+1023, map.get("double").asFloat()), 0);
1005         TestEq("{ \"double\" : 1.7976894783391937E308, \"myInt\" : 9223371743723257855, \"myString\" : \"wow\", \"myString2\" : \"incredible\", \"myVec\" : [ 99, \"wow\" ] }",
1006                 FlexBuffers.getRoot(b.getBuffer()).toString());
1007     }
1008 
testFlexBuferEmpty()1009     public static void testFlexBuferEmpty() {
1010         FlexBuffers.Blob blob = FlexBuffers.Blob.empty();
1011         FlexBuffers.Map ary = FlexBuffers.Map.empty();
1012         FlexBuffers.Vector map = FlexBuffers.Vector.empty();
1013         FlexBuffers.TypedVector typedAry = FlexBuffers.TypedVector.empty();
1014         TestEq(blob.size(), 0);
1015         TestEq(map.size(), 0);
1016         TestEq(ary.size(), 0);
1017         TestEq(typedAry.size(), 0);
1018     }
1019 
testHashMapToMap()1020     public static void testHashMapToMap() {
1021         int entriesCount = 12;
1022 
1023         HashMap<String, String> source =  new HashMap<>();
1024         for (int i = 0; i < entriesCount; i++) {
1025             source.put("foo_param_" + i, "foo_value_" + i);
1026         }
1027 
1028         FlexBuffersBuilder builder = new FlexBuffersBuilder(1000);
1029         int mapStart = builder.startMap();
1030         for (Map.Entry<String, String> entry : source.entrySet()) {
1031             builder.putString(entry.getKey(), entry.getValue());
1032         }
1033         builder.endMap(null, mapStart);
1034         ByteBuffer bb = builder.finish();
1035         bb.rewind();
1036 
1037         FlexBuffers.Reference rootReference = FlexBuffers.getRoot(bb);
1038 
1039         TestEq(rootReference.isMap(), true);
1040 
1041         FlexBuffers.Map flexMap = rootReference.asMap();
1042 
1043         FlexBuffers.KeyVector keys = flexMap.keys();
1044         FlexBuffers.Vector values = flexMap.values();
1045 
1046         TestEq(entriesCount, keys.size());
1047         TestEq(entriesCount, values.size());
1048 
1049         HashMap<String, String> result =  new HashMap<>();
1050         for (int i = 0; i < keys.size(); i++) {
1051             result.put(keys.get(i).toString(), values.get(i).asString());
1052         }
1053 
1054         TestEq(source, result);
1055     }
1056 
testBuilderGrowth()1057     public static void testBuilderGrowth() {
1058         FlexBuffersBuilder builder = new FlexBuffersBuilder();
1059         String someString = "This is a small string";
1060         builder.putString(someString);
1061         ByteBuffer b = builder.finish();
1062         TestEq(someString, FlexBuffers.getRoot(b).asString());
1063 
1064         FlexBuffersBuilder failBuilder = new FlexBuffersBuilder(ByteBuffer.allocate(1));
1065         failBuilder.putString(someString);
1066     }
1067 
testFlexBuffersUtf8Map()1068     public static void testFlexBuffersUtf8Map() {
1069         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
1070                 FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
1071 
1072         String key0 = "�� face1";
1073         String key1 = "�� face2";
1074         String key2 = "�� face3";
1075         String key3 = "trademark ®";
1076         String key4 = "€ euro";
1077         String utf8keys[] = { "�� face1", "�� face2", "�� face3", "trademark ®", "€ euro"};
1078 
1079         int map = builder.startMap();
1080 
1081         for (int i=0; i< utf8keys.length; i++) {
1082             builder.putString(utf8keys[i], utf8keys[i]);  // Testing key and string reuse.
1083         }
1084         builder.endMap(null, map);
1085         builder.finish();
1086 
1087         FlexBuffers.Map m = FlexBuffers.getRoot(builder.getBuffer()).asMap();
1088 
1089         TestEq(m.size(), 5);
1090 
1091         KeyVector kv = m.keys();
1092         for (int i=0; i< utf8keys.length; i++) {
1093             TestEq(kv.get(i).toString(), m.get(i).asString());
1094         }
1095 
1096         TestEq(m.get(key0).asString(), utf8keys[0]);
1097         TestEq(m.get(key1).asString(), utf8keys[1]);
1098         TestEq(m.get(key2).asString(), utf8keys[2]);
1099         TestEq(m.get(key3).asString(), utf8keys[3]);
1100         TestEq(m.get(key4).asString(), utf8keys[4]);
1101     }
1102 
testFlexBuffersMapLookup()1103     public static void testFlexBuffersMapLookup() {
1104         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
1105                 FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
1106 
1107         String key0 = "123";
1108         String key1 = "1234";
1109         String key2 = "12345";
1110         String[] keys = new String[]{key0, key1, key2};
1111 
1112         int map = builder.startMap();
1113 
1114         for (int i=0; i< keys.length; i++) {
1115             builder.putString(keys[i], keys[i]);  // Testing key and string reuse.
1116         }
1117         builder.endMap(null, map);
1118         builder.finish();
1119 
1120         FlexBuffers.Map m = FlexBuffers.getRoot(builder.getBuffer()).asMap();
1121         for (int i=0; i< keys.length; i++) {
1122             TestEq(m.get(keys[i]).asString(), keys[i]);
1123             TestEq(m.get(keys[i].getBytes(StandardCharsets.UTF_8)).asString(), keys[i]);
1124         }
1125     }
1126 
TestFlexBuffers()1127     public static void TestFlexBuffers() {
1128         testSingleElementByte();
1129         testSingleElementShort();
1130         testSingleElementInt();
1131         testSingleElementLong();
1132         testSingleElementFloat();
1133         testSingleElementDouble();
1134         testSingleElementSmallString();
1135         testSingleElementBigString();
1136         testSingleElementBlob();
1137         testSingleElementLongBlob();
1138         testSingleElementVector();
1139         testSingleFixedTypeVector();
1140         testSingleElementUShort();
1141         testSingleElementUInt();
1142         testSingleElementUByte();
1143         testSingleElementMap();
1144         testFlexBuffersTest();
1145         testHashMapToMap();
1146         testFlexBuferEmpty();
1147         testFlexBufferVectorStrings();
1148         testDeprecatedTypedVectorString();
1149         testBuilderGrowth();
1150         testFlexBuffersUtf8Map();
1151         testFlexBuffersMapLookup();
1152     }
1153 
TestDictionaryLookup()1154     static void TestDictionaryLookup() {
1155         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
1156         int lfIndex = LongFloatEntry.createLongFloatEntry(fbb, 0, 99);
1157         int vectorEntriesIdx = LongFloatMap.createEntriesVector(fbb, new int[] { lfIndex });
1158         int rootIdx = LongFloatMap.createLongFloatMap(fbb, vectorEntriesIdx);
1159 
1160         LongFloatMap.finishLongFloatMapBuffer(fbb, rootIdx);
1161         LongFloatMap map = LongFloatMap.getRootAsLongFloatMap(fbb.dataBuffer());
1162         TestEq(map.entriesLength(), 1);
1163 
1164         LongFloatEntry e = map.entries(0);
1165         TestEq(e.key(), 0L);
1166         TestEq(e.value(), 99.0f);
1167 
1168         LongFloatEntry e2 = map.entriesByKey(0);
1169         TestEq(e2.key(), 0L);
1170         TestEq(e2.value(), 99.0f);
1171     }
1172 
TestVectorOfBytes()1173     static void TestVectorOfBytes() {
1174         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
1175         int str = fbb.createString("ByteMonster");
1176         byte[] data = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1177         int offset = Monster.createInventoryVector(fbb, data);
1178         Monster.startMonster(fbb);
1179         Monster.addName(fbb, str);
1180         Monster.addInventory(fbb, offset);
1181         int monster1 = Monster.endMonster(fbb);
1182         Monster.finishMonsterBuffer(fbb, monster1);
1183         Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
1184 
1185         TestEq(monsterObject.inventoryLength(), data.length);
1186         TestEq(monsterObject.inventory(4), (int) data[4]);
1187         TestEq(ByteBuffer.wrap(data), monsterObject.inventoryAsByteBuffer());
1188 
1189         fbb.clear();
1190         ByteBuffer bb = ByteBuffer.wrap(data);
1191         offset = fbb.createByteVector(bb);
1192         str = fbb.createString("ByteMonster");
1193         Monster.startMonster(fbb);
1194         Monster.addName(fbb, str);
1195         Monster.addInventory(fbb, offset);
1196         monster1 = Monster.endMonster(fbb);
1197         Monster.finishMonsterBuffer(fbb, monster1);
1198         Monster monsterObject2 = Monster.getRootAsMonster(fbb.dataBuffer());
1199 
1200         TestEq(monsterObject2.inventoryLength(), data.length);
1201         for (int i = 0; i < data.length; i++) {
1202           TestEq(monsterObject2.inventory(i), (int) bb.get(i));
1203         }
1204 
1205         fbb.clear();
1206         offset = fbb.createByteVector(data, 3, 4);
1207         str = fbb.createString("ByteMonster");
1208         Monster.startMonster(fbb);
1209         Monster.addName(fbb, str);
1210         Monster.addInventory(fbb, offset);
1211         monster1 = Monster.endMonster(fbb);
1212         Monster.finishMonsterBuffer(fbb, monster1);
1213         Monster monsterObject3 = Monster.getRootAsMonster(fbb.dataBuffer());
1214 
1215         TestEq(monsterObject3.inventoryLength(), 4);
1216         TestEq(monsterObject3.inventory(0), (int) data[3]);
1217 
1218         fbb.clear();
1219         bb = ByteBuffer.wrap(data);
1220         offset = Monster.createInventoryVector(fbb, bb);
1221         str = fbb.createString("ByteMonster");
1222         Monster.startMonster(fbb);
1223         Monster.addName(fbb, str);
1224         Monster.addInventory(fbb, offset);
1225         monster1 = Monster.endMonster(fbb);
1226         Monster.finishMonsterBuffer(fbb, monster1);
1227         Monster monsterObject4 = Monster.getRootAsMonster(fbb.dataBuffer());
1228 
1229         TestEq(monsterObject4.inventoryLength(), data.length);
1230         TestEq(monsterObject4.inventory(8), (int) 8);
1231 
1232         fbb.clear();
1233         byte[] largeData = new byte[1024];
1234         offset = fbb.createByteVector(largeData);
1235         str = fbb.createString("ByteMonster");
1236         Monster.startMonster(fbb);
1237         Monster.addName(fbb, str);
1238         Monster.addInventory(fbb, offset);
1239         monster1 = Monster.endMonster(fbb);
1240         Monster.finishMonsterBuffer(fbb, monster1);
1241         Monster monsterObject5 = Monster.getRootAsMonster(fbb.dataBuffer());
1242 
1243         TestEq(monsterObject5.inventoryLength(), largeData.length);
1244         TestEq(monsterObject5.inventory(25), (int) largeData[25]);
1245 
1246         fbb.clear();
1247         bb = ByteBuffer.wrap(largeData);
1248         bb.position(512);
1249         ByteBuffer bb2 = bb.slice();
1250         TestEq(bb2.arrayOffset(), 512);
1251         offset = fbb.createByteVector(bb2);
1252         str = fbb.createString("ByteMonster");
1253         Monster.startMonster(fbb);
1254         Monster.addName(fbb, str);
1255         Monster.addInventory(fbb, offset);
1256         monster1 = Monster.endMonster(fbb);
1257         Monster.finishMonsterBuffer(fbb, monster1);
1258         Monster monsterObject6 = Monster.getRootAsMonster(fbb.dataBuffer());
1259 
1260         TestEq(monsterObject6.inventoryLength(), 512);
1261         TestEq(monsterObject6.inventory(0), (int) largeData[512]);
1262 
1263         fbb.clear();
1264         bb = ByteBuffer.wrap(largeData);
1265         bb.limit(256);
1266         offset = fbb.createByteVector(bb);
1267         str = fbb.createString("ByteMonster");
1268         Monster.startMonster(fbb);
1269         Monster.addName(fbb, str);
1270         Monster.addInventory(fbb, offset);
1271         monster1 = Monster.endMonster(fbb);
1272         Monster.finishMonsterBuffer(fbb, monster1);
1273         Monster monsterObject7 = Monster.getRootAsMonster(fbb.dataBuffer());
1274 
1275         TestEq(monsterObject7.inventoryLength(), 256);
1276 
1277         fbb.clear();
1278         bb = ByteBuffer.allocateDirect(2048);
1279         offset = fbb.createByteVector(bb);
1280         str = fbb.createString("ByteMonster");
1281         Monster.startMonster(fbb);
1282         Monster.addName(fbb, str);
1283         Monster.addInventory(fbb, offset);
1284         monster1 = Monster.endMonster(fbb);
1285         Monster.finishMonsterBuffer(fbb, monster1);
1286         Monster monsterObject8 = Monster.getRootAsMonster(fbb.dataBuffer());
1287 
1288         TestEq(monsterObject8.inventoryLength(), 2048);
1289     }
1290 
TestSharedStringPool()1291     static void TestSharedStringPool() {
1292         FlatBufferBuilder fb = new FlatBufferBuilder(1);
1293         String testString = "My string";
1294         int offset = fb.createSharedString(testString);
1295         for (int i=0; i< 10; i++) {
1296             TestEq(offset, fb.createSharedString(testString));
1297         }
1298     }
1299 
TestScalarOptional()1300     static void TestScalarOptional() {
1301         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
1302         ScalarStuff.startScalarStuff(fbb);
1303         int pos = ScalarStuff.endScalarStuff(fbb);
1304         fbb.finish(pos);
1305 
1306         ScalarStuff scalarStuff = ScalarStuff.getRootAsScalarStuff(fbb.dataBuffer());
1307         TestEq(scalarStuff.justI8(), (byte)0);
1308         TestEq(scalarStuff.maybeI8(), (byte)0);
1309         TestEq(scalarStuff.defaultI8(), (byte)42);
1310         TestEq(scalarStuff.justU8(), 0);
1311         TestEq(scalarStuff.maybeU8(), 0);
1312         TestEq(scalarStuff.defaultU8(), 42);
1313         TestEq(scalarStuff.justI16(), (short)0);
1314         TestEq(scalarStuff.maybeI16(), (short)0);
1315         TestEq(scalarStuff.defaultI16(), (short)42);
1316         TestEq(scalarStuff.justU16(), 0);
1317         TestEq(scalarStuff.maybeU16(), 0);
1318         TestEq(scalarStuff.defaultU16(), 42);
1319         TestEq(scalarStuff.justI32(), 0);
1320         TestEq(scalarStuff.maybeI32(), 0);
1321         TestEq(scalarStuff.defaultI32(), 42);
1322         TestEq(scalarStuff.justU32(), 0L);
1323         TestEq(scalarStuff.maybeU32(), 0L);
1324         TestEq(scalarStuff.defaultU32(), 42L);
1325         TestEq(scalarStuff.justI64(), 0L);
1326         TestEq(scalarStuff.maybeI64(), 0L);
1327         TestEq(scalarStuff.defaultI64(), 42L);
1328         TestEq(scalarStuff.justU64(), 0L);
1329         TestEq(scalarStuff.maybeU64(), 0L);
1330         TestEq(scalarStuff.defaultU64(), 42L);
1331         TestEq(scalarStuff.justF32(), 0.0f);
1332         TestEq(scalarStuff.maybeF32(), 0f);
1333         TestEq(scalarStuff.defaultF32(), 42.0f);
1334         TestEq(scalarStuff.justF64(), 0.0);
1335         TestEq(scalarStuff.maybeF64(), 0.0);
1336         TestEq(scalarStuff.defaultF64(), 42.0);
1337         TestEq(scalarStuff.justBool(), false);
1338         TestEq(scalarStuff.maybeBool(), false);
1339         TestEq(scalarStuff.defaultBool(), true);
1340         TestEq(scalarStuff.justEnum(), OptionalByte.None);
1341         TestEq(scalarStuff.maybeEnum(), OptionalByte.None);
1342         TestEq(scalarStuff.defaultEnum(), OptionalByte.One);
1343 
1344         TestEq(scalarStuff.hasMaybeI8(), false);
1345         TestEq(scalarStuff.hasMaybeI16(), false);
1346         TestEq(scalarStuff.hasMaybeI32(), false);
1347         TestEq(scalarStuff.hasMaybeI64(), false);
1348         TestEq(scalarStuff.hasMaybeU8(), false);
1349         TestEq(scalarStuff.hasMaybeU16(), false);
1350         TestEq(scalarStuff.hasMaybeU32(), false);
1351         TestEq(scalarStuff.hasMaybeU64(), false);
1352         TestEq(scalarStuff.hasMaybeF32(), false);
1353         TestEq(scalarStuff.hasMaybeF64(), false);
1354         TestEq(scalarStuff.hasMaybeBool(), false);
1355         TestEq(scalarStuff.hasMaybeEnum(), false);
1356 
1357         fbb.clear();
1358 
1359         ScalarStuff.startScalarStuff(fbb);
1360         ScalarStuff.addJustI8(fbb, (byte)5);
1361         ScalarStuff.addMaybeI8(fbb, (byte)5);
1362         ScalarStuff.addDefaultI8(fbb, (byte)5);
1363         ScalarStuff.addJustU8(fbb, 6);
1364         ScalarStuff.addMaybeU8(fbb, 6);
1365         ScalarStuff.addDefaultU8(fbb, 6);
1366         ScalarStuff.addJustI16(fbb, (short)7);
1367         ScalarStuff.addMaybeI16(fbb, (short)7);
1368         ScalarStuff.addDefaultI16(fbb, (short)7);
1369         ScalarStuff.addJustU16(fbb, 8);
1370         ScalarStuff.addMaybeU16(fbb, 8);
1371         ScalarStuff.addDefaultU16(fbb, 8);
1372         ScalarStuff.addJustI32(fbb, 9);
1373         ScalarStuff.addMaybeI32(fbb, 9);
1374         ScalarStuff.addDefaultI32(fbb, 9);
1375         ScalarStuff.addJustU32(fbb, (long)10);
1376         ScalarStuff.addMaybeU32(fbb, (long)10);
1377         ScalarStuff.addDefaultU32(fbb, (long)10);
1378         ScalarStuff.addJustI64(fbb, 11L);
1379         ScalarStuff.addMaybeI64(fbb, 11L);
1380         ScalarStuff.addDefaultI64(fbb, 11L);
1381         ScalarStuff.addJustU64(fbb, 12L);
1382         ScalarStuff.addMaybeU64(fbb, 12L);
1383         ScalarStuff.addDefaultU64(fbb, 12L);
1384         ScalarStuff.addJustF32(fbb, 13.0f);
1385         ScalarStuff.addMaybeF32(fbb, 13.0f);
1386         ScalarStuff.addDefaultF32(fbb, 13.0f);
1387         ScalarStuff.addJustF64(fbb, 14.0);
1388         ScalarStuff.addMaybeF64(fbb, 14.0);
1389         ScalarStuff.addDefaultF64(fbb, 14.0);
1390         ScalarStuff.addJustBool(fbb, true);
1391         ScalarStuff.addMaybeBool(fbb, true);
1392         ScalarStuff.addDefaultBool(fbb, true);
1393         ScalarStuff.addJustEnum(fbb, OptionalByte.Two);
1394         ScalarStuff.addMaybeEnum(fbb, OptionalByte.Two);
1395         ScalarStuff.addDefaultEnum(fbb, OptionalByte.Two);
1396 
1397         pos = ScalarStuff.endScalarStuff(fbb);
1398 
1399         fbb.finish(pos);
1400 
1401         scalarStuff = ScalarStuff.getRootAsScalarStuff(fbb.dataBuffer());
1402 
1403         TestEq(scalarStuff.justI8(), (byte)5);
1404         TestEq(scalarStuff.maybeI8(), (byte)5);
1405         TestEq(scalarStuff.defaultI8(), (byte)5);
1406         TestEq(scalarStuff.justU8(), 6);
1407         TestEq(scalarStuff.maybeU8(), 6);
1408         TestEq(scalarStuff.defaultU8(), 6);
1409         TestEq(scalarStuff.justI16(), (short)7);
1410         TestEq(scalarStuff.maybeI16(), (short)7);
1411         TestEq(scalarStuff.defaultI16(), (short)7);
1412         TestEq(scalarStuff.justU16(), 8);
1413         TestEq(scalarStuff.maybeU16(), 8);
1414         TestEq(scalarStuff.defaultU16(), 8);
1415         TestEq(scalarStuff.justI32(), 9);
1416         TestEq(scalarStuff.maybeI32(), 9);
1417         TestEq(scalarStuff.defaultI32(), 9);
1418         TestEq(scalarStuff.justU32(), 10L);
1419         TestEq(scalarStuff.maybeU32(), 10L);
1420         TestEq(scalarStuff.defaultU32(), 10L);
1421         TestEq(scalarStuff.justI64(), 11L);
1422         TestEq(scalarStuff.maybeI64(), 11L);
1423         TestEq(scalarStuff.defaultI64(), 11L);
1424         TestEq(scalarStuff.justU64(), 12L);
1425         TestEq(scalarStuff.maybeU64(), 12L);
1426         TestEq(scalarStuff.defaultU64(), 12L);
1427         TestEq(scalarStuff.justF32(), 13.0f);
1428         TestEq(scalarStuff.maybeF32(), 13.0f);
1429         TestEq(scalarStuff.defaultF32(), 13.0f);
1430         TestEq(scalarStuff.justF64(), 14.0);
1431         TestEq(scalarStuff.maybeF64(), 14.0);
1432         TestEq(scalarStuff.defaultF64(), 14.0);
1433         TestEq(scalarStuff.justBool(), true);
1434         TestEq(scalarStuff.maybeBool(), true);
1435         TestEq(scalarStuff.defaultBool(), true);
1436         TestEq(scalarStuff.justEnum(), OptionalByte.Two);
1437         TestEq(scalarStuff.maybeEnum(), OptionalByte.Two);
1438         TestEq(scalarStuff.defaultEnum(), OptionalByte.Two);
1439 
1440         TestEq(scalarStuff.hasMaybeI8(), true);
1441         TestEq(scalarStuff.hasMaybeI16(), true);
1442         TestEq(scalarStuff.hasMaybeI32(), true);
1443         TestEq(scalarStuff.hasMaybeI64(), true);
1444         TestEq(scalarStuff.hasMaybeU8(), true);
1445         TestEq(scalarStuff.hasMaybeU16(), true);
1446         TestEq(scalarStuff.hasMaybeU32(), true);
1447         TestEq(scalarStuff.hasMaybeU64(), true);
1448         TestEq(scalarStuff.hasMaybeF32(), true);
1449         TestEq(scalarStuff.hasMaybeF64(), true);
1450         TestEq(scalarStuff.hasMaybeBool(), true);
1451         TestEq(scalarStuff.hasMaybeEnum(), true);
1452     }
1453 
TestObject(MonsterT monster)1454     static void TestObject(MonsterT monster) {
1455         TestEq(monster.getHp(), (short) 80);
1456         TestEq(monster.getMana(), (short) 150);  // default
1457 
1458         TestEq(monster.getName(), "MyMonster");
1459         TestEq(monster.getColor(), Color.Blue);
1460         // monster.friendly() // can't access, deprecated
1461 
1462         Vec3T pos = monster.getPos();
1463         TestEq(pos.getX(), 1.0f);
1464         TestEq(pos.getY(), 2.0f);
1465         TestEq(pos.getZ(), 3.0f);
1466         TestEq(pos.getTest1(), 3.0);
1467         // issue: int != byte
1468         TestEq(pos.getTest2(), (int) Color.Green);
1469         TestT t = pos.getTest3();
1470         TestEq(t.getA(), (short) 5);
1471         TestEq(t.getB(), (byte) 6);
1472 
1473         TestEq(monster.getTest().getType(), (byte) Any.Monster);
1474         MonsterT monster2 = (MonsterT) monster.getTest().getValue();
1475         TestEq(monster2 != null, true);
1476         TestEq(monster2.getName(), "Fred");
1477 
1478         int[] inv = monster.getInventory();
1479         TestEq(inv.length, 5);
1480         int[] expInv = {0, 1, 2, 3, 4};
1481         for (int i = 0; i < inv.length; i++)
1482             TestEq(expInv[i], inv[i]);
1483 
1484         TestT[] test4 = monster.getTest4();
1485         TestT test_0 = test4[0];
1486         TestT test_1 = test4[1];
1487         TestEq(test4.length, 2);
1488         TestEq(test_0.getA(), (short) 10);
1489         TestEq(test_0.getB(), (byte) 20);
1490         TestEq(test_1.getA(), (short) 30);
1491         TestEq(test_1.getB(), (byte) 40);
1492 
1493         String[] testarrayofstring = monster.getTestarrayofstring();
1494         TestEq(testarrayofstring.length, 2);
1495         TestEq(testarrayofstring[0], "test1");
1496         TestEq(testarrayofstring[1], "test2");
1497 
1498         MonsterT[] testarrayoftables = monster.getTestarrayoftables();
1499         TestEq(testarrayoftables.length, 0);
1500 
1501         MonsterT enemy = monster.getEnemy();
1502         TestEq(enemy != null, true);
1503         TestEq(enemy.getName(), "Fred");
1504 
1505         int[] testnestedflatbuffer = monster.getTestnestedflatbuffer();
1506         TestEq(testnestedflatbuffer.length, 0);
1507 
1508         TestEq(monster.getTestempty() == null, true);
1509 
1510         TestEq(monster.getTestbool(), true);
1511 
1512         boolean[] testarrayofbools = monster.getTestarrayofbools();
1513         TestEq(testarrayofbools.length, 3);
1514         TestEq(testarrayofbools[0], true);
1515         TestEq(testarrayofbools[1], false);
1516         TestEq(testarrayofbools[2], true);
1517 
1518         TestEq(monster.getTestf(), 3.14159f);
1519         TestEq(monster.getTestf2(), 3.0f);
1520         TestEq(monster.getTestf3(), 0.0f);
1521         TestEq(monster.getTestf3(), 0.0f);
1522 
1523         AbilityT[] testarrayofsortedstruct = monster.getTestarrayofsortedstruct();
1524         TestEq(testarrayofsortedstruct.length, 3);
1525         TestEq(testarrayofsortedstruct[0].getId(), (long) 0);
1526         TestEq(testarrayofsortedstruct[1].getId(), (long) 1);
1527         TestEq(testarrayofsortedstruct[2].getId(), (long) 5);
1528         TestEq(testarrayofsortedstruct[0].getDistance(), (long) 45);
1529         TestEq(testarrayofsortedstruct[1].getDistance(), (long) 21);
1530         TestEq(testarrayofsortedstruct[2].getDistance(), (long) 12);
1531 
1532         int[] flex = monster.getFlex();
1533         TestEq(flex.length, 0);
1534 
1535         long[] vectorOfLongs = monster.getVectorOfLongs();
1536         TestEq(vectorOfLongs.length, 5);
1537         long l = 1;
1538         for (int i = 0; i < vectorOfLongs.length; i++) {
1539             TestEq(vectorOfLongs[i], l);
1540             l *= 100;
1541         }
1542 
1543         double[] vectorOfDoubles = monster.getVectorOfDoubles();
1544         TestEq(vectorOfDoubles.length, 3);
1545         TestEq(vectorOfDoubles[0], -1.7976931348623157E308);
1546         TestEq(vectorOfDoubles[1], 0.0);
1547         TestEq(vectorOfDoubles[2], 1.7976931348623157E308);
1548 
1549         TestEq(monster.getParentNamespaceTest() == null, true);
1550         ReferrableT[] vectorOfReferrables = monster.getVectorOfReferrables();
1551         TestEq(vectorOfReferrables.length, 0);
1552 
1553         TestEq(monster.getSignedEnum(), (byte) -1);
1554     }
1555 
TestPackUnpack(ByteBuffer bb)1556     static void TestPackUnpack(ByteBuffer bb) {
1557         Monster m = Monster.getRootAsMonster(bb);
1558         MonsterT mObject = m.unpack();
1559         TestObject(mObject);
1560         FlatBufferBuilder fbb = new FlatBufferBuilder();
1561         int monster = Monster.pack(fbb, mObject);
1562         Monster.finishMonsterBuffer(fbb, monster);
1563         TestBuffer(fbb.dataBuffer());
1564 
1565         byte[] bytes = mObject.serializeToBinary();
1566         MonsterT newMonsterT = MonsterT.deserializeFromBinary(bytes);
1567         TestObject(newMonsterT);
1568     }
1569 
TestEq(T a, T b)1570     static <T> void TestEq(T a, T b) {
1571         if ((a == null && a != b) || (a != null && !a.equals(b))) {
1572             System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
1573             System.out.println("FlatBuffers test FAILED: \'" + a + "\' != \'" + b + "\'");
1574             new Throwable().printStackTrace();
1575             assert false;
1576             System.exit(1);
1577         }
1578     }
1579 
1580 }
1581