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