Home | History | Annotate | Download | only in tests
      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.io.*;
     18 import java.nio.ByteBuffer;
     19 import java.nio.ByteOrder;
     20 import java.nio.channels.FileChannel;
     21 import MyGame.Example.*;
     22 import NamespaceA.*;
     23 import NamespaceA.NamespaceB.*;
     24 import com.google.flatbuffers.FlatBufferBuilder;
     25 
     26 class JavaTest {
     27     public static void main(String[] args) {
     28 
     29         // First, let's test reading a FlatBuffer generated by C++ code:
     30         // This file was generated from monsterdata_test.json
     31 
     32         byte[] data = null;
     33         File file = new File("monsterdata_test.mon");
     34         RandomAccessFile f = null;
     35         try {
     36             f = new RandomAccessFile(file, "r");
     37             data = new byte[(int)f.length()];
     38             f.readFully(data);
     39             f.close();
     40         } catch(java.io.IOException e) {
     41             System.out.println("FlatBuffers test: couldn't read file");
     42             return;
     43         }
     44 
     45         // Now test it:
     46 
     47         ByteBuffer bb = ByteBuffer.wrap(data);
     48         TestBuffer(bb);
     49 
     50         // Second, let's create a FlatBuffer from scratch in Java, and test it also.
     51         // We use an initial size of 1 to exercise the reallocation algorithm,
     52         // normally a size larger than the typical FlatBuffer you generate would be
     53         // better for performance.
     54         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
     55 
     56         TestBuilderBasics(fbb);
     57 
     58         TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
     59 
     60         TestNamespaceNesting();
     61 
     62         TestNestedFlatBuffer();
     63 
     64         TestCreateByteVector();
     65 
     66         TestCreateUninitializedVector();
     67 
     68         TestByteBufferFactory();
     69 
     70         TestSizedInputStream();
     71 
     72         System.out.println("FlatBuffers test: completed successfully");
     73     }
     74 
     75     static void TestEnums() {
     76       TestEq(Color.name(Color.Red), "Red");
     77       TestEq(Color.name(Color.Blue), "Blue");
     78       TestEq(Any.name(Any.NONE), "NONE");
     79       TestEq(Any.name(Any.Monster), "Monster");
     80     }
     81 
     82     static void TestBuffer(ByteBuffer bb) {
     83         TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
     84 
     85         Monster monster = Monster.getRootAsMonster(bb);
     86 
     87         TestEq(monster.hp(), (short)80);
     88         TestEq(monster.mana(), (short)150);  // default
     89 
     90         TestEq(monster.name(), "MyMonster");
     91         // monster.friendly() // can't access, deprecated
     92 
     93         Vec3 pos = monster.pos();
     94         TestEq(pos.x(), 1.0f);
     95         TestEq(pos.y(), 2.0f);
     96         TestEq(pos.z(), 3.0f);
     97         TestEq(pos.test1(), 3.0);
     98         TestEq(pos.test2(), Color.Green);
     99         Test t = pos.test3();
    100         TestEq(t.a(), (short)5);
    101         TestEq(t.b(), (byte)6);
    102 
    103         TestEq(monster.testType(), (byte)Any.Monster);
    104         Monster monster2 = new Monster();
    105         TestEq(monster.test(monster2) != null, true);
    106         TestEq(monster2.name(), "Fred");
    107 
    108         TestEq(monster.inventoryLength(), 5);
    109         int invsum = 0;
    110         for (int i = 0; i < monster.inventoryLength(); i++)
    111             invsum += monster.inventory(i);
    112         TestEq(invsum, 10);
    113 
    114         // Alternative way of accessing a vector:
    115         ByteBuffer ibb = monster.inventoryAsByteBuffer();
    116         invsum = 0;
    117         while (ibb.position() < ibb.limit())
    118             invsum += ibb.get();
    119         TestEq(invsum, 10);
    120 
    121         Test test_0 = monster.test4(0);
    122         Test test_1 = monster.test4(1);
    123         TestEq(monster.test4Length(), 2);
    124         TestEq(test_0.a() + test_0.b() + test_1.a() + test_1.b(), 100);
    125 
    126         TestEq(monster.testarrayofstringLength(), 2);
    127         TestEq(monster.testarrayofstring(0),"test1");
    128         TestEq(monster.testarrayofstring(1),"test2");
    129 
    130         TestEq(monster.testbool(), false);
    131     }
    132 
    133     // this method checks additional fields not present in the binary buffer read from file
    134     // these new tests are performed on top of the regular tests
    135     static void TestExtendedBuffer(ByteBuffer bb) {
    136         TestBuffer(bb);
    137 
    138         Monster monster = Monster.getRootAsMonster(bb);
    139 
    140         TestEq(monster.testhashu32Fnv1(), Integer.MAX_VALUE + 1L);
    141     }
    142 
    143     static void TestNamespaceNesting() {
    144         // reference / manipulate these to verify compilation
    145         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
    146 
    147         TableInNestedNS.startTableInNestedNS(fbb);
    148         TableInNestedNS.addFoo(fbb, 1234);
    149         int nestedTableOff = TableInNestedNS.endTableInNestedNS(fbb);
    150 
    151         TableInFirstNS.startTableInFirstNS(fbb);
    152         TableInFirstNS.addFooTable(fbb, nestedTableOff);
    153         int off = TableInFirstNS.endTableInFirstNS(fbb);
    154     }
    155 
    156     static void TestNestedFlatBuffer() {
    157         final String nestedMonsterName = "NestedMonsterName";
    158         final short nestedMonsterHp = 600;
    159         final short nestedMonsterMana = 1024;
    160 
    161         FlatBufferBuilder fbb1 = new FlatBufferBuilder(16);
    162         int str1 = fbb1.createString(nestedMonsterName);
    163         Monster.startMonster(fbb1);
    164         Monster.addName(fbb1, str1);
    165         Monster.addHp(fbb1, nestedMonsterHp);
    166         Monster.addMana(fbb1, nestedMonsterMana);
    167         int monster1 = Monster.endMonster(fbb1);
    168         Monster.finishMonsterBuffer(fbb1, monster1);
    169         byte[] fbb1Bytes = fbb1.sizedByteArray();
    170         fbb1 = null;
    171 
    172         FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
    173         int str2 = fbb2.createString("My Monster");
    174         int nestedBuffer = Monster.createTestnestedflatbufferVector(fbb2, fbb1Bytes);
    175         Monster.startMonster(fbb2);
    176         Monster.addName(fbb2, str2);
    177         Monster.addHp(fbb2, (short)50);
    178         Monster.addMana(fbb2, (short)32);
    179         Monster.addTestnestedflatbuffer(fbb2, nestedBuffer);
    180         int monster = Monster.endMonster(fbb2);
    181         Monster.finishMonsterBuffer(fbb2, monster);
    182 
    183         // Now test the data extracted from the nested buffer
    184         Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
    185         Monster nestedMonster = mons.testnestedflatbufferAsMonster();
    186 
    187         TestEq(nestedMonsterMana, nestedMonster.mana());
    188         TestEq(nestedMonsterHp, nestedMonster.hp());
    189         TestEq(nestedMonsterName, nestedMonster.name());
    190     }
    191 
    192     static void TestCreateByteVector() {
    193         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
    194         int str = fbb.createString("MyMonster");
    195         byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
    196         int vec = fbb.createByteVector(inventory);
    197         Monster.startMonster(fbb);
    198         Monster.addInventory(fbb, vec);
    199         Monster.addName(fbb, str);
    200         int monster1 = Monster.endMonster(fbb);
    201         Monster.finishMonsterBuffer(fbb, monster1);
    202         Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
    203 
    204         TestEq(monsterObject.inventory(1), (int)inventory[1]);
    205         TestEq(monsterObject.inventoryLength(), inventory.length);
    206         TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
    207     }
    208 
    209     static void TestCreateUninitializedVector() {
    210         FlatBufferBuilder fbb = new FlatBufferBuilder(16);
    211         int str = fbb.createString("MyMonster");
    212         byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
    213         ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
    214         for (byte i:inventory) {
    215             bb.put(i);
    216         }
    217         int vec = fbb.endVector();
    218         Monster.startMonster(fbb);
    219         Monster.addInventory(fbb, vec);
    220         Monster.addName(fbb, str);
    221         int monster1 = Monster.endMonster(fbb);
    222         Monster.finishMonsterBuffer(fbb, monster1);
    223         Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
    224 
    225         TestEq(monsterObject.inventory(1), (int)inventory[1]);
    226         TestEq(monsterObject.inventoryLength(), inventory.length);
    227         TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
    228     }
    229 
    230     static void TestByteBufferFactory() {
    231         final class MappedByteBufferFactory implements FlatBufferBuilder.ByteBufferFactory {
    232             @Override
    233             public ByteBuffer newByteBuffer(int capacity) {
    234                 ByteBuffer bb;
    235                 try {
    236                     bb =  new RandomAccessFile("javatest.bin", "rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, capacity).order(ByteOrder.LITTLE_ENDIAN);
    237                 } catch(Throwable e) {
    238                     System.out.println("FlatBuffers test: couldn't map ByteBuffer to a file");
    239                     bb = null;
    240                 }
    241                 return bb;
    242             }
    243         }
    244 
    245         FlatBufferBuilder fbb = new FlatBufferBuilder(1, new MappedByteBufferFactory());
    246 
    247         TestBuilderBasics(fbb);
    248     }
    249 
    250     static void TestSizedInputStream() {
    251         // Test on default FlatBufferBuilder that uses HeapByteBuffer
    252         FlatBufferBuilder fbb = new FlatBufferBuilder(1);
    253 
    254         TestBuilderBasics(fbb);
    255 
    256         InputStream in = fbb.sizedInputStream();
    257         byte[] array = fbb.sizedByteArray();
    258         int count = 0;
    259         int currentVal = 0;
    260 
    261         while (currentVal != -1 && count < array.length) {
    262             try {
    263                 currentVal = in.read();
    264             } catch(java.io.IOException e) {
    265                 System.out.println("FlatBuffers test: couldn't read from InputStream");
    266                 return;
    267             }
    268             TestEq((byte)currentVal, array[count]);
    269             count++;
    270         }
    271         TestEq(count, array.length);
    272     }
    273 
    274     static void TestBuilderBasics(FlatBufferBuilder fbb) {
    275         int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
    276         int[] off = new int[3];
    277         Monster.startMonster(fbb);
    278         Monster.addName(fbb, names[0]);
    279         off[0] = Monster.endMonster(fbb);
    280         Monster.startMonster(fbb);
    281         Monster.addName(fbb, names[1]);
    282         off[1] = Monster.endMonster(fbb);
    283         Monster.startMonster(fbb);
    284         Monster.addName(fbb, names[2]);
    285         off[2] = Monster.endMonster(fbb);
    286         int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
    287 
    288         // We set up the same values as monsterdata.json:
    289 
    290         int str = fbb.createString("MyMonster");
    291 
    292         int inv = Monster.createInventoryVector(fbb, new byte[] { 0, 1, 2, 3, 4 });
    293 
    294         int fred = fbb.createString("Fred");
    295         Monster.startMonster(fbb);
    296         Monster.addName(fbb, fred);
    297         int mon2 = Monster.endMonster(fbb);
    298 
    299         Monster.startTest4Vector(fbb, 2);
    300         Test.createTest(fbb, (short)10, (byte)20);
    301         Test.createTest(fbb, (short)30, (byte)40);
    302         int test4 = fbb.endVector();
    303 
    304         int testArrayOfString = Monster.createTestarrayofstringVector(fbb, new int[] {
    305                 fbb.createString("test1"),
    306                 fbb.createString("test2")
    307         });
    308 
    309         Monster.startMonster(fbb);
    310         Monster.addPos(fbb, Vec3.createVec3(fbb, 1.0f, 2.0f, 3.0f, 3.0,
    311                 Color.Green, (short)5, (byte)6));
    312         Monster.addHp(fbb, (short)80);
    313         Monster.addName(fbb, str);
    314         Monster.addInventory(fbb, inv);
    315         Monster.addTestType(fbb, (byte)Any.Monster);
    316         Monster.addTest(fbb, mon2);
    317         Monster.addTest4(fbb, test4);
    318         Monster.addTestarrayofstring(fbb, testArrayOfString);
    319         Monster.addTestbool(fbb, false);
    320         Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
    321         Monster.addTestarrayoftables(fbb, sortMons);
    322         int mon = Monster.endMonster(fbb);
    323 
    324         Monster.finishMonsterBuffer(fbb, mon);
    325 
    326         // Write the result to a file for debugging purposes:
    327         // Note that the binaries are not necessarily identical, since the JSON
    328         // parser may serialize in a slightly different order than the above
    329         // Java code. They are functionally equivalent though.
    330 
    331         try {
    332             FileChannel fc = new FileOutputStream("monsterdata_java_wire.mon").getChannel();
    333             fc.write(fbb.dataBuffer().duplicate());
    334             fc.close();
    335         } catch(java.io.IOException e) {
    336             System.out.println("FlatBuffers test: couldn't write file");
    337             return;
    338         }
    339 
    340         // Test it:
    341         TestExtendedBuffer(fbb.dataBuffer());
    342 
    343         // Make sure it also works with read only ByteBuffers. This is slower,
    344         // since creating strings incurs an additional copy
    345         // (see Table.__string).
    346         TestExtendedBuffer(fbb.dataBuffer().asReadOnlyBuffer());
    347 
    348         TestEnums();
    349 
    350         //Attempt to mutate Monster fields and check whether the buffer has been mutated properly
    351         // revert to original values after testing
    352         Monster monster = Monster.getRootAsMonster(fbb.dataBuffer());
    353 
    354         // mana is optional and does not exist in the buffer so the mutation should fail
    355         // the mana field should retain its default value
    356         TestEq(monster.mutateMana((short)10), false);
    357         TestEq(monster.mana(), (short)150);
    358 
    359         // Accessing a vector of sorted by the key tables
    360         TestEq(monster.testarrayoftables(0).name(), "Barney");
    361         TestEq(monster.testarrayoftables(1).name(), "Frodo");
    362         TestEq(monster.testarrayoftables(2).name(), "Wilma");
    363 
    364         // Example of searching for a table by the key
    365         TestEq(monster.testarrayoftablesByKey("Frodo").name(), "Frodo");
    366         TestEq(monster.testarrayoftablesByKey("Barney").name(), "Barney");
    367         TestEq(monster.testarrayoftablesByKey("Wilma").name(), "Wilma");
    368 
    369         // testType is an existing field and mutating it should succeed
    370         TestEq(monster.testType(), (byte)Any.Monster);
    371         TestEq(monster.mutateTestType(Any.NONE), true);
    372         TestEq(monster.testType(), (byte)Any.NONE);
    373         TestEq(monster.mutateTestType(Any.Monster), true);
    374         TestEq(monster.testType(), (byte)Any.Monster);
    375 
    376         //mutate the inventory vector
    377         TestEq(monster.mutateInventory(0, 1), true);
    378         TestEq(monster.mutateInventory(1, 2), true);
    379         TestEq(monster.mutateInventory(2, 3), true);
    380         TestEq(monster.mutateInventory(3, 4), true);
    381         TestEq(monster.mutateInventory(4, 5), true);
    382 
    383         for (int i = 0; i < monster.inventoryLength(); i++) {
    384             TestEq(monster.inventory(i), i + 1);
    385         }
    386 
    387         //reverse mutation
    388         TestEq(monster.mutateInventory(0, 0), true);
    389         TestEq(monster.mutateInventory(1, 1), true);
    390         TestEq(monster.mutateInventory(2, 2), true);
    391         TestEq(monster.mutateInventory(3, 3), true);
    392         TestEq(monster.mutateInventory(4, 4), true);
    393 
    394         // get a struct field and edit one of its fields
    395         Vec3 pos = monster.pos();
    396         TestEq(pos.x(), 1.0f);
    397         pos.mutateX(55.0f);
    398         TestEq(pos.x(), 55.0f);
    399         pos.mutateX(1.0f);
    400         TestEq(pos.x(), 1.0f);
    401     }
    402 
    403     static <T> void TestEq(T a, T b) {
    404         if (!a.equals(b)) {
    405             System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());
    406             System.out.println("FlatBuffers test FAILED: \'" + a + "\' != \'" + b + "\'");
    407             assert false;
    408             System.exit(1);
    409         }
    410     }
    411 }
    412