Fix issue #5542 (#5543)
[platform/upstream/flatbuffers.git] / tests / JavaTest.java
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 import java.util.Arrays;
18 import java.math.BigInteger;
19 import java.io.*;
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.nio.channels.FileChannel;
23 import java.util.Map;
24 import java.util.HashMap;
25 import MyGame.Example.*;
26 import NamespaceA.*;
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;
37
38 class JavaTest {
39     public static void main(String[] args) {
40
41         // First, let's test reading a FlatBuffer generated by C++ code:
42         // This file was generated from monsterdata_test.json
43
44         byte[] data = null;
45         File file = new File("monsterdata_test.mon");
46         RandomAccessFile f = null;
47         try {
48             f = new RandomAccessFile(file, "r");
49             data = new byte[(int)f.length()];
50             f.readFully(data);
51             f.close();
52         } catch(java.io.IOException e) {
53             System.out.println("FlatBuffers test: couldn't read file");
54             return;
55         }
56
57         // Now test it:
58
59         ByteBuffer bb = ByteBuffer.wrap(data);
60         TestBuffer(bb);
61
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);
67
68         TestBuilderBasics(fbb, true);
69         TestBuilderBasics(fbb, false);
70
71         TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
72
73         TestNamespaceNesting();
74
75         TestNestedFlatBuffer();
76
77         TestCreateByteVector();
78
79         TestCreateUninitializedVector();
80
81         TestByteBufferFactory();
82
83         TestSizedInputStream();
84
85         TestVectorOfUnions();
86
87         TestFixedLengthArrays();
88
89         TestFlexBuffers();
90
91         System.out.println("FlatBuffers test: completed successfully");
92     }
93
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");
99     }
100
101     static void TestBuffer(ByteBuffer bb) {
102         TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
103
104         Monster monster = Monster.getRootAsMonster(bb);
105
106         TestEq(monster.hp(), (short)80);
107         TestEq(monster.mana(), (short)150);  // default
108
109         TestEq(monster.name(), "MyMonster");
110         // monster.friendly() // can't access, deprecated
111
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);
122
123         TestEq(monster.testType(), (byte)Any.Monster);
124         Monster monster2 = new Monster();
125         TestEq(monster.test(monster2) != null, true);
126         TestEq(monster2.name(), "Fred");
127
128         TestEq(monster.inventoryLength(), 5);
129         int invsum = 0;
130         for (int i = 0; i < monster.inventoryLength(); i++)
131             invsum += monster.inventory(i);
132         TestEq(invsum, 10);
133
134         // Method using a vector access object:
135         ByteVector inventoryVector = monster.inventoryVector();
136         TestEq(inventoryVector.length(), 5);
137         invsum = 0;
138         for (int i = 0; i < inventoryVector.length(); i++)
139             invsum += inventoryVector.getAsUnsigned(i);
140         TestEq(invsum, 10);
141
142         // Alternative way of accessing a vector:
143         ByteBuffer ibb = monster.inventoryAsByteBuffer();
144         invsum = 0;
145         while (ibb.position() < ibb.limit())
146             invsum += ibb.get();
147         TestEq(invsum, 10);
148
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);
153
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);
159
160         TestEq(monster.testarrayofstringLength(), 2);
161         TestEq(monster.testarrayofstring(0),"test1");
162         TestEq(monster.testarrayofstring(1),"test2");
163
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");
169
170         TestEq(monster.testbool(), true);
171     }
172
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) {
176         TestBuffer(bb);
177
178         Monster monster = Monster.getRootAsMonster(bb);
179
180         TestEq(monster.testhashu32Fnv1(), Integer.MAX_VALUE + 1L);
181     }
182
183     static void TestNamespaceNesting() {
184         // reference / manipulate these to verify compilation
185         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
186
187         TableInNestedNS.startTableInNestedNS(fbb);
188         TableInNestedNS.addFoo(fbb, 1234);
189         int nestedTableOff = TableInNestedNS.endTableInNestedNS(fbb);
190
191         TableInFirstNS.startTableInFirstNS(fbb);
192         TableInFirstNS.addFooTable(fbb, nestedTableOff);
193         int off = TableInFirstNS.endTableInFirstNS(fbb);
194     }
195
196     static void TestNestedFlatBuffer() {
197         final String nestedMonsterName = "NestedMonsterName";
198         final short nestedMonsterHp = 600;
199         final short nestedMonsterMana = 1024;
200
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();
210         fbb1 = null;
211
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);
222
223         // Now test the data extracted from the nested buffer
224         Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
225         Monster nestedMonster = mons.testnestedflatbufferAsMonster();
226
227         TestEq(nestedMonsterMana, nestedMonster.mana());
228         TestEq(nestedMonsterHp, nestedMonster.hp());
229         TestEq(nestedMonsterName, nestedMonster.name());
230     }
231
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());
243
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);
249
250         TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
251     }
252
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) {
259             bb.put(i);
260         }
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());
268
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());
275     }
276
277     static void TestByteBufferFactory() {
278         final class MappedByteBufferFactory extends FlatBufferBuilder.ByteBufferFactory {
279             @Override
280             public ByteBuffer newByteBuffer(int capacity) {
281                 ByteBuffer bb;
282                 try {
283                     RandomAccessFile f = new RandomAccessFile("javatest.bin", "rw");
284                     bb =  f.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, capacity).order(ByteOrder.LITTLE_ENDIAN);
285                     f.close();
286                 } catch(Throwable e) {
287                     System.out.println("FlatBuffers test: couldn't map ByteBuffer to a file");
288                     bb = null;
289                 }
290                 return bb;
291             }
292         }
293
294         FlatBufferBuilder fbb = new FlatBufferBuilder(1, new MappedByteBufferFactory());
295
296         TestBuilderBasics(fbb, false);
297     }
298
299     static void TestSizedInputStream() {
300         // Test on default FlatBufferBuilder that uses HeapByteBuffer
301         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
302
303         TestBuilderBasics(fbb, false);
304
305         InputStream in = fbb.sizedInputStream();
306         byte[] array = fbb.sizedByteArray();
307         int count = 0;
308         int currentVal = 0;
309
310         while (currentVal != -1 && count < array.length) {
311             try {
312                 currentVal = in.read();
313             } catch(java.io.IOException e) {
314                 System.out.println("FlatBuffers test: couldn't read from InputStream");
315                 return;
316             }
317             TestEq((byte)currentVal, array[count]);
318             count++;
319         }
320         TestEq(count, array.length);
321     }
322
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);
336
337         // We set up the same values as monsterdata.json:
338
339         int str = fbb.createString("MyMonster");
340
341         int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
342
343         int fred = fbb.createString("Fred");
344         Monster.startMonster(fbb);
345         Monster.addName(fbb, fred);
346         int mon2 = Monster.endMonster(fbb);
347
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();
352
353         int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
354                 fbb.createString("test1"),
355                 fbb.createString("test2")
356         });
357
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);
372
373         if (sizePrefix) {
374             Monster.finishSizePrefixedMonsterBuffer(fbb, mon);
375         } else {
376             Monster.finishMonsterBuffer(fbb, mon);
377         }
378
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.
383
384         try {
385             String filename = "monsterdata_java_wire" + (sizePrefix ? "_sp" : "") + ".mon";
386             FileChannel fc = new FileOutputStream(filename).getChannel();
387             fc.write(fbb.dataBuffer().duplicate());
388             fc.close();
389         } catch(java.io.IOException e) {
390             System.out.println("FlatBuffers test: couldn't write file");
391             return;
392         }
393
394         // Test it:
395         ByteBuffer dataBuffer = fbb.dataBuffer();
396         if (sizePrefix) {
397             TestEq(ByteBufferUtil.getSizePrefix(dataBuffer) + SIZE_PREFIX_LENGTH,
398                    dataBuffer.remaining());
399             dataBuffer = ByteBufferUtil.removeSizePrefix(dataBuffer);
400         }
401         TestExtendedBuffer(dataBuffer);
402
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());
407
408         TestEnums();
409
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);
413
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);
418
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");
427
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");
435
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);
442
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);
449
450         for (int i = 0; i < monster.inventoryLength(); i++) {
451             TestEq(monster.inventory(i), i + 1);
452         }
453         ByteVector inventoryVector =  monster.inventoryVector();
454         for (int i = 0; i < inventoryVector.length(); i++) {
455             TestEq((int)inventoryVector.get(i), i + 1);
456         }
457
458         //reverse mutation
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);
464
465         // get a struct field and edit one of its fields
466         Vec3 pos = monster.pos();
467         TestEq(pos.x(), 1.0f);
468         pos.mutateX(55.0f);
469         TestEq(pos.x(), 55.0f);
470         pos.mutateX(1.0f);
471         TestEq(pos.x(), 1.0f);
472     }
473
474     static void TestVectorOfUnions() {
475         final FlatBufferBuilder fbb = new FlatBufferBuilder();
476
477         final int swordAttackDamage = 1;
478
479         final int[] characterVector = new int[] {
480             Attacker.createAttacker(fbb, swordAttackDamage),
481         };
482
483         final byte[] characterTypeVector = new byte[]{
484             Character.MuLan,
485         };
486
487         Movie.finishMovieBuffer(
488             fbb,
489             Movie.createMovie(
490                 fbb,
491                 (byte)0,
492                 (byte)0,
493                 Movie.createCharactersTypeVector(fbb, characterTypeVector),
494                 Movie.createCharactersVector(fbb, characterVector)
495             )
496         );
497
498         final Movie movie = Movie.getRootAsMovie(fbb.dataBuffer());
499         ByteVector charactersTypeByteVector = movie.charactersTypeVector();
500         UnionVector charactersVector = movie.charactersVector();
501
502         TestEq(movie.charactersTypeLength(), characterTypeVector.length);
503         TestEq(charactersTypeByteVector.length(), characterTypeVector.length);
504         TestEq(movie.charactersLength(), characterVector.length);
505         TestEq(charactersVector.length(), characterVector.length);
506
507         TestEq(movie.charactersType(0), characterTypeVector[0]);
508         TestEq(charactersTypeByteVector.get(0), characterTypeVector[0]);
509
510         TestEq(((Attacker)movie.characters(new Attacker(), 0)).swordAttackDamage(), swordAttackDamage);
511     }
512
513     static void TestFixedLengthArrays() {
514         FlatBufferBuilder builder = new FlatBufferBuilder(0);
515
516         float       a;
517         int[]       b = new int[15];
518         byte        c;
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];
523         int         e;
524         long[]      f = new long[2];
525
526         a = 0.5f;
527         for (int i = 0; i < 15; i++) b[i] = i;
528         c = 1;
529         d_a[0][0] = 1;
530         d_a[0][1] = 2;
531         d_a[1][0] = 3;
532         d_a[1][1] = 4;
533         d_b[0] = TestEnum.B;
534         d_b[1] = TestEnum.C;
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;
539         d_d[0][0] = -1;
540         d_d[0][1] = 1;
541         d_d[1][0] = -2;
542         d_d[1][1] = 2;
543         e = 2;
544         f[0] = -1;
545         f[1] = 1;
546
547         int arrayOffset = ArrayStruct.createArrayStruct(builder,
548             a, b, c, d_a, d_b, d_c, d_d, e, f);
549
550         // Create a table with the ArrayStruct.
551         ArrayTable.startArrayTable(builder);
552         ArrayTable.addA(builder, arrayOffset);
553         int tableOffset = ArrayTable.endArrayTable(builder);
554
555         ArrayTable.finishArrayTableBuffer(builder, tableOffset);
556
557         ArrayTable table = ArrayTable.getRootAsArrayTable(builder.dataBuffer());
558         NestedStruct nested = new NestedStruct();
559
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);
580     }
581
582     public static void testFlexBuffersTest() {
583         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
584                 FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
585
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();
591
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);
598
599         int map2 = builder.startMap();
600         builder.putInt("test", 200);
601         builder.endMap(null, map2);
602
603         builder.putFloat(150.9);
604         builder.putFloat(150.9999998);
605         builder.endVector("vec", vec1, false, false);
606
607         vec1 = builder.startVector();
608         builder.putInt(1);
609         builder.putInt(2);
610         builder.putInt(3);
611         builder.endVector("bar", vec1, true, false);
612
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);
619
620         builder.putBoolean("bool", true);
621         builder.putFloat("foo", 100);
622
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);
629
630         builder.endMap(null, map1);
631         builder.finish();
632
633         FlexBuffers.Map m = FlexBuffers.getRoot(builder.getBuffer()).asMap();
634
635         TestEq(m.size(), 6);
636
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
644
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++
661
662         // bar vector
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);
669
670         // bools vector
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);
678
679
680         TestEq((float)m.get("foo").asFloat(), (float) 100);
681         TestEq(m.get("unknown").isNull(), true);
682
683         // mymap vector
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\"");
693     }
694
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());
700     }
701
702     public static void testSingleElementByte() {
703         FlexBuffersBuilder builder = new FlexBuffersBuilder();
704         builder.putInt(10);
705         ByteBuffer b = builder.finish();
706         TestEq(10, FlexBuffers.getRoot(b).asInt());
707     }
708
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());
714     }
715
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());
721     }
722
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());
728     }
729
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);
735     }
736
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);
742     }
743
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());
751     }
752
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]);
763     }
764
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());
771     }
772
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());
779     }
780
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());
787     }
788
789     public static void testSingleFixedTypeVector() {
790
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};
795
796
797         FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
798                 FlexBuffersBuilder.BUILDER_FLAG_NONE);
799
800         int mapPos = builder.startMap();
801
802         int vecPos = builder.startVector();
803         for (final int i : ints) {
804             builder.putInt(i);
805         }
806         builder.endVector("ints", vecPos, true, false);
807
808         vecPos = builder.startVector();
809         for (final float i : floats) {
810             builder.putFloat(i);
811         }
812         builder.endVector("floats", vecPos, true, false);
813
814         vecPos = builder.startVector();
815         for (final String i : strings) {
816             builder.putString(i);
817         }
818         builder.endVector("strings", vecPos, true, false);
819
820         vecPos = builder.startVector();
821         for (final boolean i : booleans) {
822             builder.putBoolean(i);
823         }
824         builder.endVector("booleans", vecPos, true, false);
825
826         builder.endMap(null, mapPos);
827
828
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());
835     }
836
837     public static void testSingleElementVector() {
838         FlexBuffersBuilder b = new FlexBuffersBuilder();
839
840         int vecPos = b.startVector();
841         b.putInt(99);
842         b.putString("wow");
843         int vecpos2 = b.startVector();
844         b.putInt(99);
845         b.putString("wow");
846         b.endVector(null, vecpos2, false, false);
847         b.endVector(null, vecPos, false, false);
848         b.finish();
849
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());
858     }
859
860     public static void testSingleElementMap() {
861         FlexBuffersBuilder b = new FlexBuffersBuilder();
862
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();
868         b.putInt(99);
869         b.putString("wow");
870         b.endVector("myVec", start, false, false);
871
872         b.putFloat("double", 0x1.ffffbbbffffffP+1023);
873         b.endMap(null, mapPost);
874         b.finish();
875
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());
888     }
889
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);
899     }
900
901     public static void testHashMapToMap() {
902         int entriesCount = 12;
903
904         HashMap<String, String> source =  new HashMap<>();
905         for (int i = 0; i < entriesCount; i++) {
906             source.put("foo_param_" + i, "foo_value_" + i);
907         }
908
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());
913         }
914         builder.endMap(null, mapStart);
915         ByteBuffer bb = builder.finish();
916         bb.rewind();
917
918         FlexBuffers.Reference rootReference = FlexBuffers.getRoot(bb);
919
920         TestEq(rootReference.isMap(), true);
921
922         FlexBuffers.Map flexMap = rootReference.asMap();
923
924         FlexBuffers.KeyVector keys = flexMap.keys();
925         FlexBuffers.Vector values = flexMap.values();
926
927         TestEq(entriesCount, keys.size());
928         TestEq(entriesCount, values.size());
929
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());
933         }
934
935         TestEq(source, result);
936     }
937
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();
954         testHashMapToMap();
955         testFlexBuferEmpty();
956     }
957
958     static <T> void TestEq(T a, T b) {
959         if (!a.equals(b)) {
960             System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
961             System.out.println("FlatBuffers test FAILED: \'" + a + "\' != \'" + b + "\'");
962             new Throwable().printStackTrace();
963             assert false;
964             System.exit(1);
965         }
966     }
967 }