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