xref: /aosp_15_r20/external/flatbuffers/dart/test/flat_buffers_test.dart (revision 890232f25432b36107d06881e0a25aaa6b473652)
1*890232f2SAndroid Build Coastguard Workerimport 'dart:typed_data';
2*890232f2SAndroid Build Coastguard Workerimport 'dart:io' as io;
3*890232f2SAndroid Build Coastguard Worker
4*890232f2SAndroid Build Coastguard Workerimport 'package:path/path.dart' as path;
5*890232f2SAndroid Build Coastguard Worker
6*890232f2SAndroid Build Coastguard Workerimport 'package:flat_buffers/flat_buffers.dart';
7*890232f2SAndroid Build Coastguard Workerimport 'package:test/test.dart';
8*890232f2SAndroid Build Coastguard Workerimport 'package:test_reflective_loader/test_reflective_loader.dart';
9*890232f2SAndroid Build Coastguard Worker
10*890232f2SAndroid Build Coastguard Workerimport './monster_test_my_game.example_generated.dart' as example;
11*890232f2SAndroid Build Coastguard Workerimport './monster_test_my_game.example2_generated.dart' as example2;
12*890232f2SAndroid Build Coastguard Workerimport './list_of_enums_generated.dart' as example3;
13*890232f2SAndroid Build Coastguard Workerimport './bool_structs_generated.dart' as example4;
14*890232f2SAndroid Build Coastguard Workerimport './keyword_test_keyword_test_generated.dart' as keyword_test;
15*890232f2SAndroid Build Coastguard Worker
16*890232f2SAndroid Build Coastguard Workermain() {
17*890232f2SAndroid Build Coastguard Worker  defineReflectiveSuite(() {
18*890232f2SAndroid Build Coastguard Worker    defineReflectiveTests(BuilderTest);
19*890232f2SAndroid Build Coastguard Worker    defineReflectiveTests(ObjectAPITest);
20*890232f2SAndroid Build Coastguard Worker    defineReflectiveTests(CheckOtherLangaugesData);
21*890232f2SAndroid Build Coastguard Worker    defineReflectiveTests(GeneratorTest);
22*890232f2SAndroid Build Coastguard Worker    defineReflectiveTests(ListOfEnumsTest);
23*890232f2SAndroid Build Coastguard Worker  });
24*890232f2SAndroid Build Coastguard Worker}
25*890232f2SAndroid Build Coastguard Worker
26*890232f2SAndroid Build Coastguard Workerint indexToField(int index) {
27*890232f2SAndroid Build Coastguard Worker  return (1 + 1 + index) * 2;
28*890232f2SAndroid Build Coastguard Worker}
29*890232f2SAndroid Build Coastguard Worker
30*890232f2SAndroid Build Coastguard Worker@reflectiveTest
31*890232f2SAndroid Build Coastguard Workerclass CheckOtherLangaugesData {
32*890232f2SAndroid Build Coastguard Worker  test_cppData() async {
33*890232f2SAndroid Build Coastguard Worker    List<int> data = await io.File(path.join(
34*890232f2SAndroid Build Coastguard Worker      path.context.current,
35*890232f2SAndroid Build Coastguard Worker      'test',
36*890232f2SAndroid Build Coastguard Worker      'monsterdata_test.mon',
37*890232f2SAndroid Build Coastguard Worker    )).readAsBytes();
38*890232f2SAndroid Build Coastguard Worker    example.Monster mon = example.Monster(data);
39*890232f2SAndroid Build Coastguard Worker    expect(mon.hp, 80);
40*890232f2SAndroid Build Coastguard Worker    expect(mon.mana, 150);
41*890232f2SAndroid Build Coastguard Worker    expect(mon.name, 'MyMonster');
42*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.x, 1.0);
43*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.y, 2.0);
44*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.z, 3.0);
45*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.test1, 3.0);
46*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.test2.value, 2.0);
47*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.test3.a, 5);
48*890232f2SAndroid Build Coastguard Worker    expect(mon.pos!.test3.b, 6);
49*890232f2SAndroid Build Coastguard Worker    expect(mon.testType!.value, example.AnyTypeId.Monster.value);
50*890232f2SAndroid Build Coastguard Worker    expect(mon.test is example.Monster, true);
51*890232f2SAndroid Build Coastguard Worker    final monster2 = mon.test as example.Monster;
52*890232f2SAndroid Build Coastguard Worker    expect(monster2.name, "Fred");
53*890232f2SAndroid Build Coastguard Worker
54*890232f2SAndroid Build Coastguard Worker    expect(mon.inventory!.length, 5);
55*890232f2SAndroid Build Coastguard Worker    expect(mon.inventory!.reduce((cur, next) => cur + next), 10);
56*890232f2SAndroid Build Coastguard Worker    final test4 = mon.test4!;
57*890232f2SAndroid Build Coastguard Worker    expect(test4.length, 2);
58*890232f2SAndroid Build Coastguard Worker    expect(test4[0].a + test4[0].b + test4[1].a + test4[1].b, 100);
59*890232f2SAndroid Build Coastguard Worker    expect(mon.testarrayofstring!.length, 2);
60*890232f2SAndroid Build Coastguard Worker    expect(mon.testarrayofstring![0], "test1");
61*890232f2SAndroid Build Coastguard Worker    expect(mon.testarrayofstring![1], "test2");
62*890232f2SAndroid Build Coastguard Worker
63*890232f2SAndroid Build Coastguard Worker    // this will fail if accessing any field fails.
64*890232f2SAndroid Build Coastguard Worker    expect(
65*890232f2SAndroid Build Coastguard Worker      mon.toString(),
66*890232f2SAndroid Build Coastguard Worker      'Monster{'
67*890232f2SAndroid Build Coastguard Worker      'pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color{value: 2}, test3: Test{a: 5, b: 6}}, '
68*890232f2SAndroid Build Coastguard Worker      'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], '
69*890232f2SAndroid Build Coastguard Worker      'color: Color{value: 8}, testType: AnyTypeId{value: 1}, '
70*890232f2SAndroid Build Coastguard Worker      'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
71*890232f2SAndroid Build Coastguard Worker      'inventory: null, color: Color{value: 8}, testType: null, '
72*890232f2SAndroid Build Coastguard Worker      'test: null, test4: null, testarrayofstring: null, '
73*890232f2SAndroid Build Coastguard Worker      'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
74*890232f2SAndroid Build Coastguard Worker      'testempty: null, testbool: false, testhashs32Fnv1: 0, '
75*890232f2SAndroid Build Coastguard Worker      'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
76*890232f2SAndroid Build Coastguard Worker      'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
77*890232f2SAndroid Build Coastguard Worker      'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
78*890232f2SAndroid Build Coastguard Worker      'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
79*890232f2SAndroid Build Coastguard Worker      'testarrayofsortedstruct: null, flex: null, test5: null, '
80*890232f2SAndroid Build Coastguard Worker      'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
81*890232f2SAndroid Build Coastguard Worker      'vectorOfReferrables: null, singleWeakReference: 0, '
82*890232f2SAndroid Build Coastguard Worker      'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
83*890232f2SAndroid Build Coastguard Worker      'coOwningReference: 0, vectorOfCoOwningReferences: null, '
84*890232f2SAndroid Build Coastguard Worker      'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
85*890232f2SAndroid Build Coastguard Worker      'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
86*890232f2SAndroid Build Coastguard Worker      'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
87*890232f2SAndroid Build Coastguard Worker      'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
88*890232f2SAndroid Build Coastguard Worker      'nativeInline: null, '
89*890232f2SAndroid Build Coastguard Worker      'longEnumNonEnumDefault: LongEnum{value: 0}, '
90*890232f2SAndroid Build Coastguard Worker      'longEnumNormalDefault: LongEnum{value: 2}}, '
91*890232f2SAndroid Build Coastguard Worker      'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
92*890232f2SAndroid Build Coastguard Worker      'testarrayofstring: [test1, test2], testarrayoftables: null, '
93*890232f2SAndroid Build Coastguard Worker      'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
94*890232f2SAndroid Build Coastguard Worker      'inventory: null, color: Color{value: 8}, testType: null, '
95*890232f2SAndroid Build Coastguard Worker      'test: null, test4: null, testarrayofstring: null, '
96*890232f2SAndroid Build Coastguard Worker      'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
97*890232f2SAndroid Build Coastguard Worker      'testempty: null, testbool: false, testhashs32Fnv1: 0, '
98*890232f2SAndroid Build Coastguard Worker      'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
99*890232f2SAndroid Build Coastguard Worker      'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
100*890232f2SAndroid Build Coastguard Worker      'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
101*890232f2SAndroid Build Coastguard Worker      'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
102*890232f2SAndroid Build Coastguard Worker      'testarrayofsortedstruct: null, flex: null, test5: null, '
103*890232f2SAndroid Build Coastguard Worker      'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
104*890232f2SAndroid Build Coastguard Worker      'vectorOfReferrables: null, singleWeakReference: 0, '
105*890232f2SAndroid Build Coastguard Worker      'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
106*890232f2SAndroid Build Coastguard Worker      'coOwningReference: 0, vectorOfCoOwningReferences: null, '
107*890232f2SAndroid Build Coastguard Worker      'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
108*890232f2SAndroid Build Coastguard Worker      'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
109*890232f2SAndroid Build Coastguard Worker      'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
110*890232f2SAndroid Build Coastguard Worker      'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
111*890232f2SAndroid Build Coastguard Worker      'nativeInline: null, '
112*890232f2SAndroid Build Coastguard Worker      'longEnumNonEnumDefault: LongEnum{value: 0}, '
113*890232f2SAndroid Build Coastguard Worker      'longEnumNormalDefault: LongEnum{value: 2}}, '
114*890232f2SAndroid Build Coastguard Worker      'testnestedflatbuffer: null, testempty: null, testbool: true, '
115*890232f2SAndroid Build Coastguard Worker      'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, '
116*890232f2SAndroid Build Coastguard Worker      'testhashs64Fnv1: 7930699090847568257, '
117*890232f2SAndroid Build Coastguard Worker      'testhashu64Fnv1: 7930699090847568257, '
118*890232f2SAndroid Build Coastguard Worker      'testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, '
119*890232f2SAndroid Build Coastguard Worker      'testhashs64Fnv1a: 4898026182817603057, '
120*890232f2SAndroid Build Coastguard Worker      'testhashu64Fnv1a: 4898026182817603057, '
121*890232f2SAndroid Build Coastguard Worker      'testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, '
122*890232f2SAndroid Build Coastguard Worker      'testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: ['
123*890232f2SAndroid Build Coastguard Worker      'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, '
124*890232f2SAndroid Build Coastguard Worker      'Ability{id: 5, distance: 12}], '
125*890232f2SAndroid Build Coastguard Worker      'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
126*890232f2SAndroid Build Coastguard Worker      'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], '
127*890232f2SAndroid Build Coastguard Worker      'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], '
128*890232f2SAndroid Build Coastguard Worker      'parentNamespaceTest: null, vectorOfReferrables: null, '
129*890232f2SAndroid Build Coastguard Worker      'singleWeakReference: 0, vectorOfWeakReferences: null, '
130*890232f2SAndroid Build Coastguard Worker      'vectorOfStrongReferrables: null, coOwningReference: 0, '
131*890232f2SAndroid Build Coastguard Worker      'vectorOfCoOwningReferences: null, nonOwningReference: 0, '
132*890232f2SAndroid Build Coastguard Worker      'vectorOfNonOwningReferences: null, '
133*890232f2SAndroid Build Coastguard Worker      'anyUniqueType: null, anyUnique: null, '
134*890232f2SAndroid Build Coastguard Worker      'anyAmbiguousType: null, '
135*890232f2SAndroid Build Coastguard Worker      'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
136*890232f2SAndroid Build Coastguard Worker      'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: '
137*890232f2SAndroid Build Coastguard Worker      'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
138*890232f2SAndroid Build Coastguard Worker      'nativeInline: Test{a: 1, b: 2}, '
139*890232f2SAndroid Build Coastguard Worker      'longEnumNonEnumDefault: LongEnum{value: 0}, '
140*890232f2SAndroid Build Coastguard Worker      'longEnumNormalDefault: LongEnum{value: 2}}',
141*890232f2SAndroid Build Coastguard Worker    );
142*890232f2SAndroid Build Coastguard Worker  }
143*890232f2SAndroid Build Coastguard Worker}
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard Worker/// Test a custom, fixed-memory allocator (no actual allocations performed)
146*890232f2SAndroid Build Coastguard Workerclass CustomAllocator extends Allocator {
147*890232f2SAndroid Build Coastguard Worker  final _memory = ByteData(10 * 1024);
148*890232f2SAndroid Build Coastguard Worker  int _used = 0;
149*890232f2SAndroid Build Coastguard Worker
150*890232f2SAndroid Build Coastguard Worker  Uint8List buffer(int size) => _memory.buffer.asUint8List(_used - size, size);
151*890232f2SAndroid Build Coastguard Worker
152*890232f2SAndroid Build Coastguard Worker  @override
153*890232f2SAndroid Build Coastguard Worker  ByteData allocate(int size) {
154*890232f2SAndroid Build Coastguard Worker    if (size > _memory.lengthInBytes) {
155*890232f2SAndroid Build Coastguard Worker      throw UnsupportedError('Trying to allocate too much');
156*890232f2SAndroid Build Coastguard Worker    }
157*890232f2SAndroid Build Coastguard Worker    _used = size;
158*890232f2SAndroid Build Coastguard Worker    return ByteData.sublistView(_memory, 0, size);
159*890232f2SAndroid Build Coastguard Worker  }
160*890232f2SAndroid Build Coastguard Worker
161*890232f2SAndroid Build Coastguard Worker  @override
162*890232f2SAndroid Build Coastguard Worker  void deallocate(ByteData _) {}
163*890232f2SAndroid Build Coastguard Worker}
164*890232f2SAndroid Build Coastguard Worker
165*890232f2SAndroid Build Coastguard Worker@reflectiveTest
166*890232f2SAndroid Build Coastguard Workerclass BuilderTest {
167*890232f2SAndroid Build Coastguard Worker  void test_monsterBuilder([Builder? builder]) {
168*890232f2SAndroid Build Coastguard Worker    final fbBuilder = builder ?? Builder();
169*890232f2SAndroid Build Coastguard Worker    final str = fbBuilder.writeString('MyMonster');
170*890232f2SAndroid Build Coastguard Worker
171*890232f2SAndroid Build Coastguard Worker    fbBuilder.writeString('test1');
172*890232f2SAndroid Build Coastguard Worker    fbBuilder.writeString('test2', asciiOptimization: true);
173*890232f2SAndroid Build Coastguard Worker    final testArrayOfString = fbBuilder.endStructVector(2);
174*890232f2SAndroid Build Coastguard Worker
175*890232f2SAndroid Build Coastguard Worker    final fred = fbBuilder.writeString('Fred');
176*890232f2SAndroid Build Coastguard Worker
177*890232f2SAndroid Build Coastguard Worker    final List<int> treasure = [0, 1, 2, 3, 4];
178*890232f2SAndroid Build Coastguard Worker    final inventory = fbBuilder.writeListUint8(treasure);
179*890232f2SAndroid Build Coastguard Worker
180*890232f2SAndroid Build Coastguard Worker    final monBuilder = example.MonsterBuilder(fbBuilder)
181*890232f2SAndroid Build Coastguard Worker      ..begin()
182*890232f2SAndroid Build Coastguard Worker      ..addNameOffset(fred);
183*890232f2SAndroid Build Coastguard Worker    final mon2 = monBuilder.finish();
184*890232f2SAndroid Build Coastguard Worker
185*890232f2SAndroid Build Coastguard Worker    final testBuilder = example.TestBuilder(fbBuilder);
186*890232f2SAndroid Build Coastguard Worker    testBuilder.finish(10, 20);
187*890232f2SAndroid Build Coastguard Worker    testBuilder.finish(30, 40);
188*890232f2SAndroid Build Coastguard Worker    final test4 = fbBuilder.endStructVector(2);
189*890232f2SAndroid Build Coastguard Worker
190*890232f2SAndroid Build Coastguard Worker    monBuilder
191*890232f2SAndroid Build Coastguard Worker      ..begin()
192*890232f2SAndroid Build Coastguard Worker      ..addPos(
193*890232f2SAndroid Build Coastguard Worker        example.Vec3Builder(fbBuilder).finish(
194*890232f2SAndroid Build Coastguard Worker          1.0,
195*890232f2SAndroid Build Coastguard Worker          2.0,
196*890232f2SAndroid Build Coastguard Worker          3.0,
197*890232f2SAndroid Build Coastguard Worker          3.0,
198*890232f2SAndroid Build Coastguard Worker          example.Color.Green,
199*890232f2SAndroid Build Coastguard Worker          () => testBuilder.finish(5, 6),
200*890232f2SAndroid Build Coastguard Worker        ),
201*890232f2SAndroid Build Coastguard Worker      )
202*890232f2SAndroid Build Coastguard Worker      ..addHp(80)
203*890232f2SAndroid Build Coastguard Worker      ..addNameOffset(str)
204*890232f2SAndroid Build Coastguard Worker      ..addInventoryOffset(inventory)
205*890232f2SAndroid Build Coastguard Worker      ..addTestType(example.AnyTypeId.Monster)
206*890232f2SAndroid Build Coastguard Worker      ..addTestOffset(mon2)
207*890232f2SAndroid Build Coastguard Worker      ..addTest4Offset(test4)
208*890232f2SAndroid Build Coastguard Worker      ..addTestarrayofstringOffset(testArrayOfString);
209*890232f2SAndroid Build Coastguard Worker    final mon = monBuilder.finish();
210*890232f2SAndroid Build Coastguard Worker    fbBuilder.finish(mon);
211*890232f2SAndroid Build Coastguard Worker  }
212*890232f2SAndroid Build Coastguard Worker
213*890232f2SAndroid Build Coastguard Worker  void test_error_addInt32_withoutStartTable([Builder? builder]) {
214*890232f2SAndroid Build Coastguard Worker    builder ??= Builder();
215*890232f2SAndroid Build Coastguard Worker    expect(() {
216*890232f2SAndroid Build Coastguard Worker      builder!.addInt32(0, 0);
217*890232f2SAndroid Build Coastguard Worker    }, throwsA(isA<AssertionError>()));
218*890232f2SAndroid Build Coastguard Worker  }
219*890232f2SAndroid Build Coastguard Worker
220*890232f2SAndroid Build Coastguard Worker  void test_error_addOffset_withoutStartTable() {
221*890232f2SAndroid Build Coastguard Worker    Builder builder = Builder();
222*890232f2SAndroid Build Coastguard Worker    expect(() {
223*890232f2SAndroid Build Coastguard Worker      builder.addOffset(0, 0);
224*890232f2SAndroid Build Coastguard Worker    }, throwsA(isA<AssertionError>()));
225*890232f2SAndroid Build Coastguard Worker  }
226*890232f2SAndroid Build Coastguard Worker
227*890232f2SAndroid Build Coastguard Worker  void test_error_endTable_withoutStartTable() {
228*890232f2SAndroid Build Coastguard Worker    Builder builder = Builder();
229*890232f2SAndroid Build Coastguard Worker    expect(() {
230*890232f2SAndroid Build Coastguard Worker      builder.endTable();
231*890232f2SAndroid Build Coastguard Worker    }, throwsA(isA<AssertionError>()));
232*890232f2SAndroid Build Coastguard Worker  }
233*890232f2SAndroid Build Coastguard Worker
234*890232f2SAndroid Build Coastguard Worker  void test_error_startTable_duringTable() {
235*890232f2SAndroid Build Coastguard Worker    Builder builder = Builder();
236*890232f2SAndroid Build Coastguard Worker    builder.startTable(0);
237*890232f2SAndroid Build Coastguard Worker    expect(() {
238*890232f2SAndroid Build Coastguard Worker      builder.startTable(0);
239*890232f2SAndroid Build Coastguard Worker    }, throwsA(isA<AssertionError>()));
240*890232f2SAndroid Build Coastguard Worker  }
241*890232f2SAndroid Build Coastguard Worker
242*890232f2SAndroid Build Coastguard Worker  void test_error_writeString_duringTable() {
243*890232f2SAndroid Build Coastguard Worker    Builder builder = Builder();
244*890232f2SAndroid Build Coastguard Worker    builder.startTable(1);
245*890232f2SAndroid Build Coastguard Worker    expect(() {
246*890232f2SAndroid Build Coastguard Worker      builder.writeString('12345');
247*890232f2SAndroid Build Coastguard Worker    }, throwsA(isA<AssertionError>()));
248*890232f2SAndroid Build Coastguard Worker  }
249*890232f2SAndroid Build Coastguard Worker
250*890232f2SAndroid Build Coastguard Worker  void test_file_identifier() {
251*890232f2SAndroid Build Coastguard Worker    Uint8List byteList;
252*890232f2SAndroid Build Coastguard Worker    {
253*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
254*890232f2SAndroid Build Coastguard Worker      builder.startTable(0);
255*890232f2SAndroid Build Coastguard Worker      int offset = builder.endTable();
256*890232f2SAndroid Build Coastguard Worker      builder.finish(offset, 'Az~ÿ');
257*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
258*890232f2SAndroid Build Coastguard Worker    }
259*890232f2SAndroid Build Coastguard Worker    // Convert byteList to a ByteData so that we can read data from it.
260*890232f2SAndroid Build Coastguard Worker    ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
261*890232f2SAndroid Build Coastguard Worker    // First 4 bytes are an offset to the table data.
262*890232f2SAndroid Build Coastguard Worker    int tableDataLoc = byteData.getUint32(0, Endian.little);
263*890232f2SAndroid Build Coastguard Worker    // Next 4 bytes are the file identifier.
264*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint8(4), 65); // 'a'
265*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint8(5), 122); // 'z'
266*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint8(6), 126); // '~'
267*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint8(7), 255); // 'ÿ'
268*890232f2SAndroid Build Coastguard Worker    // First 4 bytes of the table data are a backwards offset to the vtable.
269*890232f2SAndroid Build Coastguard Worker    int vTableLoc =
270*890232f2SAndroid Build Coastguard Worker        tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little);
271*890232f2SAndroid Build Coastguard Worker    // First 2 bytes of the vtable are the size of the vtable in bytes, which
272*890232f2SAndroid Build Coastguard Worker    // should be 4.
273*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint16(vTableLoc, Endian.little), 4);
274*890232f2SAndroid Build Coastguard Worker    // Next 2 bytes are the size of the object in bytes (including the vtable
275*890232f2SAndroid Build Coastguard Worker    // pointer), which should be 4.
276*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
277*890232f2SAndroid Build Coastguard Worker  }
278*890232f2SAndroid Build Coastguard Worker
279*890232f2SAndroid Build Coastguard Worker  void test_low() {
280*890232f2SAndroid Build Coastguard Worker    final allocator = CustomAllocator();
281*890232f2SAndroid Build Coastguard Worker    final builder = Builder(initialSize: 0, allocator: allocator);
282*890232f2SAndroid Build Coastguard Worker
283*890232f2SAndroid Build Coastguard Worker    builder.putUint8(1);
284*890232f2SAndroid Build Coastguard Worker    expect(allocator.buffer(builder.size()), [1]);
285*890232f2SAndroid Build Coastguard Worker
286*890232f2SAndroid Build Coastguard Worker    builder.putUint32(2);
287*890232f2SAndroid Build Coastguard Worker    expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]);
288*890232f2SAndroid Build Coastguard Worker
289*890232f2SAndroid Build Coastguard Worker    builder.putUint8(3);
290*890232f2SAndroid Build Coastguard Worker    expect(
291*890232f2SAndroid Build Coastguard Worker        allocator.buffer(builder.size()), [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
292*890232f2SAndroid Build Coastguard Worker
293*890232f2SAndroid Build Coastguard Worker    builder.putUint8(4);
294*890232f2SAndroid Build Coastguard Worker    expect(
295*890232f2SAndroid Build Coastguard Worker        allocator.buffer(builder.size()), [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
296*890232f2SAndroid Build Coastguard Worker
297*890232f2SAndroid Build Coastguard Worker    builder.putUint8(5);
298*890232f2SAndroid Build Coastguard Worker    expect(
299*890232f2SAndroid Build Coastguard Worker        allocator.buffer(builder.size()), [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
300*890232f2SAndroid Build Coastguard Worker
301*890232f2SAndroid Build Coastguard Worker    builder.putUint32(6);
302*890232f2SAndroid Build Coastguard Worker    expect(allocator.buffer(builder.size()),
303*890232f2SAndroid Build Coastguard Worker        [6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
304*890232f2SAndroid Build Coastguard Worker  }
305*890232f2SAndroid Build Coastguard Worker
306*890232f2SAndroid Build Coastguard Worker  void test_table_default() {
307*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
308*890232f2SAndroid Build Coastguard Worker    {
309*890232f2SAndroid Build Coastguard Worker      final builder = Builder(initialSize: 0, allocator: CustomAllocator());
310*890232f2SAndroid Build Coastguard Worker      builder.startTable(2);
311*890232f2SAndroid Build Coastguard Worker      builder.addInt32(0, 10, 10);
312*890232f2SAndroid Build Coastguard Worker      builder.addInt32(1, 20, 10);
313*890232f2SAndroid Build Coastguard Worker      int offset = builder.endTable();
314*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
315*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
316*890232f2SAndroid Build Coastguard Worker      expect(builder.size(), byteList.length);
317*890232f2SAndroid Build Coastguard Worker    }
318*890232f2SAndroid Build Coastguard Worker    // read and verify
319*890232f2SAndroid Build Coastguard Worker    BufferContext buffer = BufferContext.fromBytes(byteList);
320*890232f2SAndroid Build Coastguard Worker    int objectOffset = buffer.derefObject(0);
321*890232f2SAndroid Build Coastguard Worker    // was not written, so uses the new default value
322*890232f2SAndroid Build Coastguard Worker    expect(
323*890232f2SAndroid Build Coastguard Worker        const Int32Reader()
324*890232f2SAndroid Build Coastguard Worker            .vTableGet(buffer, objectOffset, indexToField(0), 15),
325*890232f2SAndroid Build Coastguard Worker        15);
326*890232f2SAndroid Build Coastguard Worker    // has the written value
327*890232f2SAndroid Build Coastguard Worker    expect(
328*890232f2SAndroid Build Coastguard Worker        const Int32Reader()
329*890232f2SAndroid Build Coastguard Worker            .vTableGet(buffer, objectOffset, indexToField(1), 15),
330*890232f2SAndroid Build Coastguard Worker        20);
331*890232f2SAndroid Build Coastguard Worker  }
332*890232f2SAndroid Build Coastguard Worker
333*890232f2SAndroid Build Coastguard Worker  void test_table_format([Builder? builder]) {
334*890232f2SAndroid Build Coastguard Worker    Uint8List byteList;
335*890232f2SAndroid Build Coastguard Worker    {
336*890232f2SAndroid Build Coastguard Worker      builder ??= Builder(initialSize: 0);
337*890232f2SAndroid Build Coastguard Worker      builder.startTable(3);
338*890232f2SAndroid Build Coastguard Worker      builder.addInt32(0, 10);
339*890232f2SAndroid Build Coastguard Worker      builder.addInt32(1, 20);
340*890232f2SAndroid Build Coastguard Worker      builder.addInt32(2, 30);
341*890232f2SAndroid Build Coastguard Worker      builder.finish(builder.endTable());
342*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
343*890232f2SAndroid Build Coastguard Worker    }
344*890232f2SAndroid Build Coastguard Worker    // Convert byteList to a ByteData so that we can read data from it.
345*890232f2SAndroid Build Coastguard Worker    ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
346*890232f2SAndroid Build Coastguard Worker    // First 4 bytes are an offset to the table data.
347*890232f2SAndroid Build Coastguard Worker    int tableDataLoc = byteData.getUint32(0, Endian.little);
348*890232f2SAndroid Build Coastguard Worker    // First 4 bytes of the table data are a backwards offset to the vtable.
349*890232f2SAndroid Build Coastguard Worker    int vTableLoc =
350*890232f2SAndroid Build Coastguard Worker        tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little);
351*890232f2SAndroid Build Coastguard Worker    // First 2 bytes of the vtable are the size of the vtable in bytes, which
352*890232f2SAndroid Build Coastguard Worker    // should be 10.
353*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint16(vTableLoc, Endian.little), 10);
354*890232f2SAndroid Build Coastguard Worker    // Next 2 bytes are the size of the object in bytes (including the vtable
355*890232f2SAndroid Build Coastguard Worker    // pointer), which should be 16.
356*890232f2SAndroid Build Coastguard Worker    expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
357*890232f2SAndroid Build Coastguard Worker    // Remaining 6 bytes are the offsets within the object where the ints are
358*890232f2SAndroid Build Coastguard Worker    // located.
359*890232f2SAndroid Build Coastguard Worker    for (int i = 0; i < 3; i++) {
360*890232f2SAndroid Build Coastguard Worker      int offset = byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
361*890232f2SAndroid Build Coastguard Worker      expect(
362*890232f2SAndroid Build Coastguard Worker          byteData.getInt32(tableDataLoc + offset, Endian.little), 10 + 10 * i);
363*890232f2SAndroid Build Coastguard Worker    }
364*890232f2SAndroid Build Coastguard Worker  }
365*890232f2SAndroid Build Coastguard Worker
366*890232f2SAndroid Build Coastguard Worker  void test_table_string() {
367*890232f2SAndroid Build Coastguard Worker    String latinString = 'test';
368*890232f2SAndroid Build Coastguard Worker    String unicodeString = 'Проба пера';
369*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
370*890232f2SAndroid Build Coastguard Worker    {
371*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
372*890232f2SAndroid Build Coastguard Worker      int? latinStringOffset =
373*890232f2SAndroid Build Coastguard Worker          builder.writeString(latinString, asciiOptimization: true);
374*890232f2SAndroid Build Coastguard Worker      int? unicodeStringOffset =
375*890232f2SAndroid Build Coastguard Worker          builder.writeString(unicodeString, asciiOptimization: true);
376*890232f2SAndroid Build Coastguard Worker      builder.startTable(2);
377*890232f2SAndroid Build Coastguard Worker      builder.addOffset(0, latinStringOffset);
378*890232f2SAndroid Build Coastguard Worker      builder.addOffset(1, unicodeStringOffset);
379*890232f2SAndroid Build Coastguard Worker      int offset = builder.endTable();
380*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
381*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
382*890232f2SAndroid Build Coastguard Worker    }
383*890232f2SAndroid Build Coastguard Worker    // read and verify
384*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
385*890232f2SAndroid Build Coastguard Worker    int objectOffset = buf.derefObject(0);
386*890232f2SAndroid Build Coastguard Worker    expect(
387*890232f2SAndroid Build Coastguard Worker        const StringReader()
388*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(0)),
389*890232f2SAndroid Build Coastguard Worker        latinString);
390*890232f2SAndroid Build Coastguard Worker    expect(
391*890232f2SAndroid Build Coastguard Worker        const StringReader(asciiOptimization: true)
392*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(1)),
393*890232f2SAndroid Build Coastguard Worker        unicodeString);
394*890232f2SAndroid Build Coastguard Worker  }
395*890232f2SAndroid Build Coastguard Worker
396*890232f2SAndroid Build Coastguard Worker  void test_table_types([Builder? builder]) {
397*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
398*890232f2SAndroid Build Coastguard Worker    {
399*890232f2SAndroid Build Coastguard Worker      builder ??= Builder(initialSize: 0);
400*890232f2SAndroid Build Coastguard Worker      int? stringOffset = builder.writeString('12345');
401*890232f2SAndroid Build Coastguard Worker      builder.startTable(7);
402*890232f2SAndroid Build Coastguard Worker      builder.addBool(0, true);
403*890232f2SAndroid Build Coastguard Worker      builder.addInt8(1, 10);
404*890232f2SAndroid Build Coastguard Worker      builder.addInt32(2, 20);
405*890232f2SAndroid Build Coastguard Worker      builder.addOffset(3, stringOffset);
406*890232f2SAndroid Build Coastguard Worker      builder.addInt32(4, 40);
407*890232f2SAndroid Build Coastguard Worker      builder.addUint32(5, 0x9ABCDEF0);
408*890232f2SAndroid Build Coastguard Worker      builder.addUint8(6, 0x9A);
409*890232f2SAndroid Build Coastguard Worker      int offset = builder.endTable();
410*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
411*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
412*890232f2SAndroid Build Coastguard Worker    }
413*890232f2SAndroid Build Coastguard Worker    // read and verify
414*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
415*890232f2SAndroid Build Coastguard Worker    int objectOffset = buf.derefObject(0);
416*890232f2SAndroid Build Coastguard Worker    expect(
417*890232f2SAndroid Build Coastguard Worker        const BoolReader()
418*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(0)),
419*890232f2SAndroid Build Coastguard Worker        true);
420*890232f2SAndroid Build Coastguard Worker    expect(
421*890232f2SAndroid Build Coastguard Worker        const Int8Reader()
422*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(1)),
423*890232f2SAndroid Build Coastguard Worker        10);
424*890232f2SAndroid Build Coastguard Worker    expect(
425*890232f2SAndroid Build Coastguard Worker        const Int32Reader()
426*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(2)),
427*890232f2SAndroid Build Coastguard Worker        20);
428*890232f2SAndroid Build Coastguard Worker    expect(
429*890232f2SAndroid Build Coastguard Worker        const StringReader()
430*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(3)),
431*890232f2SAndroid Build Coastguard Worker        '12345');
432*890232f2SAndroid Build Coastguard Worker    expect(
433*890232f2SAndroid Build Coastguard Worker        const Int32Reader()
434*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(4)),
435*890232f2SAndroid Build Coastguard Worker        40);
436*890232f2SAndroid Build Coastguard Worker    expect(
437*890232f2SAndroid Build Coastguard Worker        const Uint32Reader()
438*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(5)),
439*890232f2SAndroid Build Coastguard Worker        0x9ABCDEF0);
440*890232f2SAndroid Build Coastguard Worker    expect(
441*890232f2SAndroid Build Coastguard Worker        const Uint8Reader()
442*890232f2SAndroid Build Coastguard Worker            .vTableGetNullable(buf, objectOffset, indexToField(6)),
443*890232f2SAndroid Build Coastguard Worker        0x9A);
444*890232f2SAndroid Build Coastguard Worker  }
445*890232f2SAndroid Build Coastguard Worker
446*890232f2SAndroid Build Coastguard Worker  void test_writeList_of_Uint32() {
447*890232f2SAndroid Build Coastguard Worker    List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
448*890232f2SAndroid Build Coastguard Worker    // write
449*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
450*890232f2SAndroid Build Coastguard Worker    {
451*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
452*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListUint32(values);
453*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
454*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
455*890232f2SAndroid Build Coastguard Worker    }
456*890232f2SAndroid Build Coastguard Worker    // read and verify
457*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
458*890232f2SAndroid Build Coastguard Worker    List<int> items = const Uint32ListReader().read(buf, 0);
459*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(4));
460*890232f2SAndroid Build Coastguard Worker    expect(items, orderedEquals(values));
461*890232f2SAndroid Build Coastguard Worker  }
462*890232f2SAndroid Build Coastguard Worker
463*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofBool() {
464*890232f2SAndroid Build Coastguard Worker    void verifyListBooleans(int len, List<int> trueBits) {
465*890232f2SAndroid Build Coastguard Worker      // write
466*890232f2SAndroid Build Coastguard Worker      List<int> byteList;
467*890232f2SAndroid Build Coastguard Worker      {
468*890232f2SAndroid Build Coastguard Worker        Builder builder = Builder(initialSize: 0);
469*890232f2SAndroid Build Coastguard Worker        List<bool> values = List<bool>.filled(len, false);
470*890232f2SAndroid Build Coastguard Worker        for (int bit in trueBits) {
471*890232f2SAndroid Build Coastguard Worker          values[bit] = true;
472*890232f2SAndroid Build Coastguard Worker        }
473*890232f2SAndroid Build Coastguard Worker        int offset = builder.writeListBool(values);
474*890232f2SAndroid Build Coastguard Worker        builder.finish(offset);
475*890232f2SAndroid Build Coastguard Worker        byteList = builder.buffer;
476*890232f2SAndroid Build Coastguard Worker      }
477*890232f2SAndroid Build Coastguard Worker      // read and verify
478*890232f2SAndroid Build Coastguard Worker      BufferContext buf = BufferContext.fromBytes(byteList);
479*890232f2SAndroid Build Coastguard Worker      List<bool> items = const BoolListReader().read(buf, 0);
480*890232f2SAndroid Build Coastguard Worker      expect(items, hasLength(len));
481*890232f2SAndroid Build Coastguard Worker      for (int i = 0; i < items.length; i++) {
482*890232f2SAndroid Build Coastguard Worker        expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
483*890232f2SAndroid Build Coastguard Worker      }
484*890232f2SAndroid Build Coastguard Worker    }
485*890232f2SAndroid Build Coastguard Worker
486*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(0, <int>[]);
487*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(1, <int>[]);
488*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(1, <int>[0]);
489*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(31, <int>[0, 1]);
490*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
491*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(31, <int>[0, 30]);
492*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
493*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
494*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
495*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(63, <int>[]);
496*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
497*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(63, List<int>.generate(63, (i) => i));
498*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(64, <int>[]);
499*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
500*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(64, <int>[1, 2, 62]);
501*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(64, <int>[0, 1, 2, 63]);
502*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(64, List<int>.generate(64, (i) => i));
503*890232f2SAndroid Build Coastguard Worker    verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
504*890232f2SAndroid Build Coastguard Worker  }
505*890232f2SAndroid Build Coastguard Worker
506*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofInt32() {
507*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
508*890232f2SAndroid Build Coastguard Worker    {
509*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
510*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
511*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
512*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
513*890232f2SAndroid Build Coastguard Worker    }
514*890232f2SAndroid Build Coastguard Worker    // read and verify
515*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
516*890232f2SAndroid Build Coastguard Worker    List<int> items = const ListReader<int>(Int32Reader()).read(buf, 0);
517*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(5));
518*890232f2SAndroid Build Coastguard Worker    expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
519*890232f2SAndroid Build Coastguard Worker  }
520*890232f2SAndroid Build Coastguard Worker
521*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofFloat64() {
522*890232f2SAndroid Build Coastguard Worker    List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
523*890232f2SAndroid Build Coastguard Worker    // write
524*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
525*890232f2SAndroid Build Coastguard Worker    {
526*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
527*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListFloat64(values);
528*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
529*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
530*890232f2SAndroid Build Coastguard Worker    }
531*890232f2SAndroid Build Coastguard Worker
532*890232f2SAndroid Build Coastguard Worker    // read and verify
533*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
534*890232f2SAndroid Build Coastguard Worker    List<double> items = const Float64ListReader().read(buf, 0);
535*890232f2SAndroid Build Coastguard Worker
536*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(values.length));
537*890232f2SAndroid Build Coastguard Worker    for (int i = 0; i < values.length; i++) {
538*890232f2SAndroid Build Coastguard Worker      expect(values[i], closeTo(items[i], .001));
539*890232f2SAndroid Build Coastguard Worker    }
540*890232f2SAndroid Build Coastguard Worker  }
541*890232f2SAndroid Build Coastguard Worker
542*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofFloat32() {
543*890232f2SAndroid Build Coastguard Worker    List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
544*890232f2SAndroid Build Coastguard Worker    // write
545*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
546*890232f2SAndroid Build Coastguard Worker    {
547*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
548*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListFloat32(values);
549*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
550*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
551*890232f2SAndroid Build Coastguard Worker    }
552*890232f2SAndroid Build Coastguard Worker    // read and verify
553*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
554*890232f2SAndroid Build Coastguard Worker    List<double> items = const Float32ListReader().read(buf, 0);
555*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(5));
556*890232f2SAndroid Build Coastguard Worker    for (int i = 0; i < values.length; i++) {
557*890232f2SAndroid Build Coastguard Worker      expect(values[i], closeTo(items[i], .001));
558*890232f2SAndroid Build Coastguard Worker    }
559*890232f2SAndroid Build Coastguard Worker  }
560*890232f2SAndroid Build Coastguard Worker
561*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofObjects([Builder? builder]) {
562*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
563*890232f2SAndroid Build Coastguard Worker    {
564*890232f2SAndroid Build Coastguard Worker      builder ??= Builder(initialSize: 0);
565*890232f2SAndroid Build Coastguard Worker      // write the object #1
566*890232f2SAndroid Build Coastguard Worker      int object1;
567*890232f2SAndroid Build Coastguard Worker      {
568*890232f2SAndroid Build Coastguard Worker        builder.startTable(2);
569*890232f2SAndroid Build Coastguard Worker        builder.addInt32(0, 10);
570*890232f2SAndroid Build Coastguard Worker        builder.addInt32(1, 20);
571*890232f2SAndroid Build Coastguard Worker        object1 = builder.endTable();
572*890232f2SAndroid Build Coastguard Worker      }
573*890232f2SAndroid Build Coastguard Worker      // write the object #1
574*890232f2SAndroid Build Coastguard Worker      int object2;
575*890232f2SAndroid Build Coastguard Worker      {
576*890232f2SAndroid Build Coastguard Worker        builder.startTable(2);
577*890232f2SAndroid Build Coastguard Worker        builder.addInt32(0, 100);
578*890232f2SAndroid Build Coastguard Worker        builder.addInt32(1, 200);
579*890232f2SAndroid Build Coastguard Worker        object2 = builder.endTable();
580*890232f2SAndroid Build Coastguard Worker      }
581*890232f2SAndroid Build Coastguard Worker      // write the list
582*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeList([object1, object2]);
583*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
584*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
585*890232f2SAndroid Build Coastguard Worker    }
586*890232f2SAndroid Build Coastguard Worker    // read and verify
587*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
588*890232f2SAndroid Build Coastguard Worker    List<TestPointImpl> items =
589*890232f2SAndroid Build Coastguard Worker        const ListReader<TestPointImpl>(TestPointReader()).read(buf, 0);
590*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(2));
591*890232f2SAndroid Build Coastguard Worker    expect(items[0].x, 10);
592*890232f2SAndroid Build Coastguard Worker    expect(items[0].y, 20);
593*890232f2SAndroid Build Coastguard Worker    expect(items[1].x, 100);
594*890232f2SAndroid Build Coastguard Worker    expect(items[1].y, 200);
595*890232f2SAndroid Build Coastguard Worker  }
596*890232f2SAndroid Build Coastguard Worker
597*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofStrings_asRoot() {
598*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
599*890232f2SAndroid Build Coastguard Worker    {
600*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
601*890232f2SAndroid Build Coastguard Worker      int? str1 = builder.writeString('12345');
602*890232f2SAndroid Build Coastguard Worker      int? str2 = builder.writeString('ABC');
603*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeList([str1, str2]);
604*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
605*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
606*890232f2SAndroid Build Coastguard Worker    }
607*890232f2SAndroid Build Coastguard Worker    // read and verify
608*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
609*890232f2SAndroid Build Coastguard Worker    List<String> items = const ListReader<String>(StringReader()).read(buf, 0);
610*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(2));
611*890232f2SAndroid Build Coastguard Worker    expect(items, contains('12345'));
612*890232f2SAndroid Build Coastguard Worker    expect(items, contains('ABC'));
613*890232f2SAndroid Build Coastguard Worker  }
614*890232f2SAndroid Build Coastguard Worker
615*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofStrings_inObject([Builder? builder]) {
616*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
617*890232f2SAndroid Build Coastguard Worker    {
618*890232f2SAndroid Build Coastguard Worker      builder ??= Builder(initialSize: 0);
619*890232f2SAndroid Build Coastguard Worker      int listOffset = builder.writeList(
620*890232f2SAndroid Build Coastguard Worker          [builder.writeString('12345'), builder.writeString('ABC')]);
621*890232f2SAndroid Build Coastguard Worker      builder.startTable(1);
622*890232f2SAndroid Build Coastguard Worker      builder.addOffset(0, listOffset);
623*890232f2SAndroid Build Coastguard Worker      int offset = builder.endTable();
624*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
625*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
626*890232f2SAndroid Build Coastguard Worker    }
627*890232f2SAndroid Build Coastguard Worker    // read and verify
628*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
629*890232f2SAndroid Build Coastguard Worker    StringListWrapperImpl reader = StringListWrapperReader().read(buf, 0);
630*890232f2SAndroid Build Coastguard Worker    List<String>? items = reader.items;
631*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(2));
632*890232f2SAndroid Build Coastguard Worker    expect(items, contains('12345'));
633*890232f2SAndroid Build Coastguard Worker    expect(items, contains('ABC'));
634*890232f2SAndroid Build Coastguard Worker  }
635*890232f2SAndroid Build Coastguard Worker
636*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofUint32() {
637*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
638*890232f2SAndroid Build Coastguard Worker    {
639*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
640*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
641*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
642*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
643*890232f2SAndroid Build Coastguard Worker    }
644*890232f2SAndroid Build Coastguard Worker    // read and verify
645*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
646*890232f2SAndroid Build Coastguard Worker    List<int> items = const Uint32ListReader().read(buf, 0);
647*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(3));
648*890232f2SAndroid Build Coastguard Worker    expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
649*890232f2SAndroid Build Coastguard Worker  }
650*890232f2SAndroid Build Coastguard Worker
651*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofUint16() {
652*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
653*890232f2SAndroid Build Coastguard Worker    {
654*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
655*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListUint16(<int>[1, 2, 60000]);
656*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
657*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
658*890232f2SAndroid Build Coastguard Worker    }
659*890232f2SAndroid Build Coastguard Worker    // read and verify
660*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
661*890232f2SAndroid Build Coastguard Worker    List<int> items = const Uint16ListReader().read(buf, 0);
662*890232f2SAndroid Build Coastguard Worker    expect(items, hasLength(3));
663*890232f2SAndroid Build Coastguard Worker    expect(items, orderedEquals(<int>[1, 2, 60000]));
664*890232f2SAndroid Build Coastguard Worker  }
665*890232f2SAndroid Build Coastguard Worker
666*890232f2SAndroid Build Coastguard Worker  void test_writeList_ofUint8() {
667*890232f2SAndroid Build Coastguard Worker    List<int> byteList;
668*890232f2SAndroid Build Coastguard Worker    {
669*890232f2SAndroid Build Coastguard Worker      Builder builder = Builder(initialSize: 0);
670*890232f2SAndroid Build Coastguard Worker      int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A, 0xFA]);
671*890232f2SAndroid Build Coastguard Worker      builder.finish(offset);
672*890232f2SAndroid Build Coastguard Worker      byteList = builder.buffer;
673*890232f2SAndroid Build Coastguard Worker    }
674*890232f2SAndroid Build Coastguard Worker    // read and verify
675*890232f2SAndroid Build Coastguard Worker    BufferContext buf = BufferContext.fromBytes(byteList);
676*890232f2SAndroid Build Coastguard Worker    const buffOffset = 8; // 32-bit offset to the list, + 32-bit length
677*890232f2SAndroid Build Coastguard Worker    for (final lazy in [true, false]) {
678*890232f2SAndroid Build Coastguard Worker      List<int> items = Uint8ListReader(lazy: lazy).read(buf, 0);
679*890232f2SAndroid Build Coastguard Worker      expect(items, hasLength(6));
680*890232f2SAndroid Build Coastguard Worker      expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A, 0xFA]));
681*890232f2SAndroid Build Coastguard Worker
682*890232f2SAndroid Build Coastguard Worker      // overwrite the buffer to verify the laziness
683*890232f2SAndroid Build Coastguard Worker      buf.buffer.setUint8(buffOffset + 1, 99);
684*890232f2SAndroid Build Coastguard Worker      expect(items, orderedEquals(<int>[1, lazy ? 99 : 2, 3, 4, 0x9A, 0xFA]));
685*890232f2SAndroid Build Coastguard Worker
686*890232f2SAndroid Build Coastguard Worker      // restore the previous value for the next loop
687*890232f2SAndroid Build Coastguard Worker      buf.buffer.setUint8(buffOffset + 1, 2);
688*890232f2SAndroid Build Coastguard Worker    }
689*890232f2SAndroid Build Coastguard Worker  }
690*890232f2SAndroid Build Coastguard Worker
691*890232f2SAndroid Build Coastguard Worker  void test_reset() {
692*890232f2SAndroid Build Coastguard Worker    // We'll run a selection of tests , reusing the builder between them.
693*890232f2SAndroid Build Coastguard Worker    final testCases = <void Function(Builder?)>[
694*890232f2SAndroid Build Coastguard Worker      test_monsterBuilder,
695*890232f2SAndroid Build Coastguard Worker      test_error_addInt32_withoutStartTable,
696*890232f2SAndroid Build Coastguard Worker      test_table_format,
697*890232f2SAndroid Build Coastguard Worker      test_table_types,
698*890232f2SAndroid Build Coastguard Worker      test_writeList_ofObjects,
699*890232f2SAndroid Build Coastguard Worker      test_writeList_ofStrings_inObject
700*890232f2SAndroid Build Coastguard Worker    ];
701*890232f2SAndroid Build Coastguard Worker
702*890232f2SAndroid Build Coastguard Worker    // Execute all test cases in all permutations of their order.
703*890232f2SAndroid Build Coastguard Worker    // To do that, we generate permutations of test case indexes.
704*890232f2SAndroid Build Coastguard Worker    final testCasesPermutations =
705*890232f2SAndroid Build Coastguard Worker        _permutationsOf(List.generate(testCases.length, (index) => index));
706*890232f2SAndroid Build Coastguard Worker    expect(testCasesPermutations.length, _factorial(testCases.length));
707*890232f2SAndroid Build Coastguard Worker
708*890232f2SAndroid Build Coastguard Worker    for (var indexes in testCasesPermutations) {
709*890232f2SAndroid Build Coastguard Worker      // print the order so failures are reproducible
710*890232f2SAndroid Build Coastguard Worker      printOnFailure('Running reset() test cases in order: $indexes');
711*890232f2SAndroid Build Coastguard Worker
712*890232f2SAndroid Build Coastguard Worker      Builder? builder;
713*890232f2SAndroid Build Coastguard Worker      for (var index in indexes) {
714*890232f2SAndroid Build Coastguard Worker        if (builder == null) {
715*890232f2SAndroid Build Coastguard Worker          // Initial size small enough so at least one test case increases it.
716*890232f2SAndroid Build Coastguard Worker          // On the other hand, it's large enough so that some test cases don't.
717*890232f2SAndroid Build Coastguard Worker          builder = Builder(initialSize: 32);
718*890232f2SAndroid Build Coastguard Worker        } else {
719*890232f2SAndroid Build Coastguard Worker          builder.reset();
720*890232f2SAndroid Build Coastguard Worker        }
721*890232f2SAndroid Build Coastguard Worker        testCases[index](builder);
722*890232f2SAndroid Build Coastguard Worker      }
723*890232f2SAndroid Build Coastguard Worker    }
724*890232f2SAndroid Build Coastguard Worker  }
725*890232f2SAndroid Build Coastguard Worker
726*890232f2SAndroid Build Coastguard Worker  // Generate permutations of the given list
727*890232f2SAndroid Build Coastguard Worker  List<List<T>> _permutationsOf<T>(List<T> source) {
728*890232f2SAndroid Build Coastguard Worker    final result = <List<T>>[];
729*890232f2SAndroid Build Coastguard Worker
730*890232f2SAndroid Build Coastguard Worker    void permutate(List<T> items, int startAt) {
731*890232f2SAndroid Build Coastguard Worker      for (var i = startAt; i < items.length; i++) {
732*890232f2SAndroid Build Coastguard Worker        List<T> permutation = items.toList(growable: false);
733*890232f2SAndroid Build Coastguard Worker        permutation[i] = items[startAt];
734*890232f2SAndroid Build Coastguard Worker        permutation[startAt] = items[i];
735*890232f2SAndroid Build Coastguard Worker
736*890232f2SAndroid Build Coastguard Worker        // add the current list upon reaching the end
737*890232f2SAndroid Build Coastguard Worker        if (startAt == items.length - 1) {
738*890232f2SAndroid Build Coastguard Worker          result.add(items);
739*890232f2SAndroid Build Coastguard Worker        } else {
740*890232f2SAndroid Build Coastguard Worker          permutate(permutation, startAt + 1);
741*890232f2SAndroid Build Coastguard Worker        }
742*890232f2SAndroid Build Coastguard Worker      }
743*890232f2SAndroid Build Coastguard Worker    }
744*890232f2SAndroid Build Coastguard Worker
745*890232f2SAndroid Build Coastguard Worker    permutate(source, 0);
746*890232f2SAndroid Build Coastguard Worker    return result;
747*890232f2SAndroid Build Coastguard Worker  }
748*890232f2SAndroid Build Coastguard Worker
749*890232f2SAndroid Build Coastguard Worker  // a very simple implementation of n!
750*890232f2SAndroid Build Coastguard Worker  int _factorial(int n) {
751*890232f2SAndroid Build Coastguard Worker    var result = 1;
752*890232f2SAndroid Build Coastguard Worker    for (var i = 2; i <= n; i++) {
753*890232f2SAndroid Build Coastguard Worker      result *= i;
754*890232f2SAndroid Build Coastguard Worker    }
755*890232f2SAndroid Build Coastguard Worker    return result;
756*890232f2SAndroid Build Coastguard Worker  }
757*890232f2SAndroid Build Coastguard Worker}
758*890232f2SAndroid Build Coastguard Worker
759*890232f2SAndroid Build Coastguard Worker@reflectiveTest
760*890232f2SAndroid Build Coastguard Workerclass ObjectAPITest {
761*890232f2SAndroid Build Coastguard Worker  void test_tableStat() {
762*890232f2SAndroid Build Coastguard Worker    final object1 = example.StatT(count: 3, id: "foo", val: 4);
763*890232f2SAndroid Build Coastguard Worker    expect(object1 is Packable, isTrue);
764*890232f2SAndroid Build Coastguard Worker    final fbb = Builder();
765*890232f2SAndroid Build Coastguard Worker    fbb.finish(object1.pack(fbb));
766*890232f2SAndroid Build Coastguard Worker    final object2 = example.Stat(fbb.buffer).unpack();
767*890232f2SAndroid Build Coastguard Worker    expect(object2.count, object1.count);
768*890232f2SAndroid Build Coastguard Worker    expect(object2.id, object1.id);
769*890232f2SAndroid Build Coastguard Worker    expect(object2.val, object1.val);
770*890232f2SAndroid Build Coastguard Worker    expect(object2.toString(), object1.toString());
771*890232f2SAndroid Build Coastguard Worker  }
772*890232f2SAndroid Build Coastguard Worker
773*890232f2SAndroid Build Coastguard Worker  void test_tableMonster() {
774*890232f2SAndroid Build Coastguard Worker    final monster = example.MonsterT()
775*890232f2SAndroid Build Coastguard Worker      ..pos = example.Vec3T(
776*890232f2SAndroid Build Coastguard Worker          x: 1,
777*890232f2SAndroid Build Coastguard Worker          y: 2,
778*890232f2SAndroid Build Coastguard Worker          z: 3,
779*890232f2SAndroid Build Coastguard Worker          test1: 4.0,
780*890232f2SAndroid Build Coastguard Worker          test2: example.Color.Red,
781*890232f2SAndroid Build Coastguard Worker          test3: example.TestT(a: 1, b: 2))
782*890232f2SAndroid Build Coastguard Worker      ..mana = 2
783*890232f2SAndroid Build Coastguard Worker      ..name = 'Monstrous'
784*890232f2SAndroid Build Coastguard Worker      ..inventory = [24, 42]
785*890232f2SAndroid Build Coastguard Worker      ..color = example.Color.Green
786*890232f2SAndroid Build Coastguard Worker      // TODO be smarter for unions and automatically set the `type` field?
787*890232f2SAndroid Build Coastguard Worker      ..testType = example.AnyTypeId.MyGame_Example2_Monster
788*890232f2SAndroid Build Coastguard Worker      ..test = example2.MonsterT()
789*890232f2SAndroid Build Coastguard Worker      ..test4 = [example.TestT(a: 3, b: 4), example.TestT(a: 5, b: 6)]
790*890232f2SAndroid Build Coastguard Worker      ..testarrayofstring = ["foo", "bar"]
791*890232f2SAndroid Build Coastguard Worker      ..testarrayoftables = [example.MonsterT(name: 'Oof')]
792*890232f2SAndroid Build Coastguard Worker      ..enemy = example.MonsterT(name: 'Enemy')
793*890232f2SAndroid Build Coastguard Worker      ..testarrayofbools = [false, true, false]
794*890232f2SAndroid Build Coastguard Worker      ..testf = 42.24
795*890232f2SAndroid Build Coastguard Worker      ..testarrayofsortedstruct = [
796*890232f2SAndroid Build Coastguard Worker        example.AbilityT(id: 1, distance: 5),
797*890232f2SAndroid Build Coastguard Worker        example.AbilityT(id: 3, distance: 7)
798*890232f2SAndroid Build Coastguard Worker      ]
799*890232f2SAndroid Build Coastguard Worker      ..vectorOfLongs = [5, 6, 7]
800*890232f2SAndroid Build Coastguard Worker      ..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2]
801*890232f2SAndroid Build Coastguard Worker      ..anyAmbiguousType = example.AnyAmbiguousAliasesTypeId.M2
802*890232f2SAndroid Build Coastguard Worker      ..anyAmbiguous = null
803*890232f2SAndroid Build Coastguard Worker      ..vectorOfEnums = [example.Color.Blue, example.Color.Green]
804*890232f2SAndroid Build Coastguard Worker      ..signedEnum = example.Race.None;
805*890232f2SAndroid Build Coastguard Worker
806*890232f2SAndroid Build Coastguard Worker    final fbBuilder = Builder();
807*890232f2SAndroid Build Coastguard Worker    final offset = monster.pack(fbBuilder);
808*890232f2SAndroid Build Coastguard Worker    expect(offset, isNonZero);
809*890232f2SAndroid Build Coastguard Worker    fbBuilder.finish(offset);
810*890232f2SAndroid Build Coastguard Worker    final data = fbBuilder.buffer;
811*890232f2SAndroid Build Coastguard Worker
812*890232f2SAndroid Build Coastguard Worker    // TODO currently broken because of struct builder issue, see #6688
813*890232f2SAndroid Build Coastguard Worker    // final monster2 = example.Monster(data); // Monster (reader)
814*890232f2SAndroid Build Coastguard Worker    // expect(
815*890232f2SAndroid Build Coastguard Worker    //     // map Monster => MonsterT, Vec3 => Vec3T, ...
816*890232f2SAndroid Build Coastguard Worker    //     monster2.toString().replaceAllMapped(
817*890232f2SAndroid Build Coastguard Worker    //         RegExp('([a-zA-z0-9]+){'), (match) => match.group(1) + 'T{'),
818*890232f2SAndroid Build Coastguard Worker    //     monster.toString());
819*890232f2SAndroid Build Coastguard Worker    //
820*890232f2SAndroid Build Coastguard Worker    // final monster3 = monster2.unpack(); // MonsterT
821*890232f2SAndroid Build Coastguard Worker    // expect(monster3.toString(), monster.toString());
822*890232f2SAndroid Build Coastguard Worker  }
823*890232f2SAndroid Build Coastguard Worker
824*890232f2SAndroid Build Coastguard Worker  void test_Lists() {
825*890232f2SAndroid Build Coastguard Worker    // Ensure unpack() reads lists eagerly by reusing the same builder and
826*890232f2SAndroid Build Coastguard Worker    // overwriting data. Why: because standard reader reads lists lazily...
827*890232f2SAndroid Build Coastguard Worker    final fbb = Builder();
828*890232f2SAndroid Build Coastguard Worker
829*890232f2SAndroid Build Coastguard Worker    final object1 = example.TypeAliasesT(v8: [1, 2, 3], vf64: [5, 6]);
830*890232f2SAndroid Build Coastguard Worker    fbb.finish(object1.pack(fbb));
831*890232f2SAndroid Build Coastguard Worker    final object1Read = example.TypeAliases(fbb.buffer).unpack();
832*890232f2SAndroid Build Coastguard Worker
833*890232f2SAndroid Build Coastguard Worker    // overwrite the original buffer by writing to the same builder
834*890232f2SAndroid Build Coastguard Worker    fbb.reset();
835*890232f2SAndroid Build Coastguard Worker    final object2 = example.TypeAliasesT(v8: [7, 8, 9], vf64: [10, 11]);
836*890232f2SAndroid Build Coastguard Worker    fbb.finish(object2.pack(fbb));
837*890232f2SAndroid Build Coastguard Worker    final object2Read = example.TypeAliases(fbb.buffer).unpack();
838*890232f2SAndroid Build Coastguard Worker
839*890232f2SAndroid Build Coastguard Worker    // this is fine even with lazy lists:
840*890232f2SAndroid Build Coastguard Worker    expect(object2.toString(), object2Read.toString());
841*890232f2SAndroid Build Coastguard Worker
842*890232f2SAndroid Build Coastguard Worker    // this fails with lazy lists:
843*890232f2SAndroid Build Coastguard Worker    expect(object1.toString(), object1Read.toString());
844*890232f2SAndroid Build Coastguard Worker
845*890232f2SAndroid Build Coastguard Worker    // empty list must be serialized as such (were stored NULL before v2.0)
846*890232f2SAndroid Build Coastguard Worker    fbb.reset();
847*890232f2SAndroid Build Coastguard Worker    final object3 = example.TypeAliasesT(v8: [], vf64: null);
848*890232f2SAndroid Build Coastguard Worker    fbb.finish(object3.pack(fbb));
849*890232f2SAndroid Build Coastguard Worker    final object3Read = example.TypeAliases(fbb.buffer).unpack();
850*890232f2SAndroid Build Coastguard Worker    expect(object3.toString(), object3Read.toString());
851*890232f2SAndroid Build Coastguard Worker  }
852*890232f2SAndroid Build Coastguard Worker}
853*890232f2SAndroid Build Coastguard Worker
854*890232f2SAndroid Build Coastguard Workerclass StringListWrapperImpl {
855*890232f2SAndroid Build Coastguard Worker  final BufferContext bp;
856*890232f2SAndroid Build Coastguard Worker  final int offset;
857*890232f2SAndroid Build Coastguard Worker
858*890232f2SAndroid Build Coastguard Worker  StringListWrapperImpl(this.bp, this.offset);
859*890232f2SAndroid Build Coastguard Worker
860*890232f2SAndroid Build Coastguard Worker  List<String>? get items => const ListReader<String>(StringReader())
861*890232f2SAndroid Build Coastguard Worker      .vTableGetNullable(bp, offset, indexToField(0));
862*890232f2SAndroid Build Coastguard Worker}
863*890232f2SAndroid Build Coastguard Worker
864*890232f2SAndroid Build Coastguard Workerclass StringListWrapperReader extends TableReader<StringListWrapperImpl> {
865*890232f2SAndroid Build Coastguard Worker  const StringListWrapperReader();
866*890232f2SAndroid Build Coastguard Worker
867*890232f2SAndroid Build Coastguard Worker  @override
868*890232f2SAndroid Build Coastguard Worker  StringListWrapperImpl createObject(BufferContext object, int offset) {
869*890232f2SAndroid Build Coastguard Worker    return StringListWrapperImpl(object, offset);
870*890232f2SAndroid Build Coastguard Worker  }
871*890232f2SAndroid Build Coastguard Worker}
872*890232f2SAndroid Build Coastguard Worker
873*890232f2SAndroid Build Coastguard Workerclass TestPointImpl {
874*890232f2SAndroid Build Coastguard Worker  final BufferContext bp;
875*890232f2SAndroid Build Coastguard Worker  final int offset;
876*890232f2SAndroid Build Coastguard Worker
877*890232f2SAndroid Build Coastguard Worker  TestPointImpl(this.bp, this.offset);
878*890232f2SAndroid Build Coastguard Worker
879*890232f2SAndroid Build Coastguard Worker  int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
880*890232f2SAndroid Build Coastguard Worker
881*890232f2SAndroid Build Coastguard Worker  int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
882*890232f2SAndroid Build Coastguard Worker}
883*890232f2SAndroid Build Coastguard Worker
884*890232f2SAndroid Build Coastguard Workerclass TestPointReader extends TableReader<TestPointImpl> {
885*890232f2SAndroid Build Coastguard Worker  const TestPointReader();
886*890232f2SAndroid Build Coastguard Worker
887*890232f2SAndroid Build Coastguard Worker  @override
888*890232f2SAndroid Build Coastguard Worker  TestPointImpl createObject(BufferContext object, int offset) {
889*890232f2SAndroid Build Coastguard Worker    return TestPointImpl(object, offset);
890*890232f2SAndroid Build Coastguard Worker  }
891*890232f2SAndroid Build Coastguard Worker}
892*890232f2SAndroid Build Coastguard Worker
893*890232f2SAndroid Build Coastguard Worker@reflectiveTest
894*890232f2SAndroid Build Coastguard Workerclass GeneratorTest {
895*890232f2SAndroid Build Coastguard Worker  void test_constantEnumValues() async {
896*890232f2SAndroid Build Coastguard Worker    expect(example.Color.values, same(example.Color.values));
897*890232f2SAndroid Build Coastguard Worker    expect(example.Race.values, same(example.Race.values));
898*890232f2SAndroid Build Coastguard Worker    expect(example.AnyTypeId.values, same(example.AnyTypeId.values));
899*890232f2SAndroid Build Coastguard Worker    expect(example.AnyUniqueAliasesTypeId.values,
900*890232f2SAndroid Build Coastguard Worker        same(example.AnyUniqueAliasesTypeId.values));
901*890232f2SAndroid Build Coastguard Worker    expect(example.AnyAmbiguousAliasesTypeId.values,
902*890232f2SAndroid Build Coastguard Worker        same(example.AnyAmbiguousAliasesTypeId.values));
903*890232f2SAndroid Build Coastguard Worker  }
904*890232f2SAndroid Build Coastguard Worker}
905*890232f2SAndroid Build Coastguard Worker
906*890232f2SAndroid Build Coastguard Worker// See #6869
907*890232f2SAndroid Build Coastguard Worker@reflectiveTest
908*890232f2SAndroid Build Coastguard Workerclass ListOfEnumsTest {
909*890232f2SAndroid Build Coastguard Worker  void test_listOfEnums() async {
910*890232f2SAndroid Build Coastguard Worker    var mytable = example3.MyTableObjectBuilder(options: [
911*890232f2SAndroid Build Coastguard Worker      example3.OptionsEnum.A,
912*890232f2SAndroid Build Coastguard Worker      example3.OptionsEnum.B,
913*890232f2SAndroid Build Coastguard Worker      example3.OptionsEnum.C
914*890232f2SAndroid Build Coastguard Worker    ]);
915*890232f2SAndroid Build Coastguard Worker    var bytes = mytable.toBytes();
916*890232f2SAndroid Build Coastguard Worker    var mytable_read = example3.MyTable(bytes);
917*890232f2SAndroid Build Coastguard Worker    expect(mytable_read.options![0].value, example3.OptionsEnum.A.value);
918*890232f2SAndroid Build Coastguard Worker    expect(mytable_read.options![1].value, example3.OptionsEnum.B.value);
919*890232f2SAndroid Build Coastguard Worker    expect(mytable_read.options![2].value, example3.OptionsEnum.C.value);
920*890232f2SAndroid Build Coastguard Worker  }
921*890232f2SAndroid Build Coastguard Worker}
922*890232f2SAndroid Build Coastguard Worker
923*890232f2SAndroid Build Coastguard Worker@reflectiveTest
924*890232f2SAndroid Build Coastguard Workerclass BoolInStructTest {
925*890232f2SAndroid Build Coastguard Worker  void test_boolInStruct() async {
926*890232f2SAndroid Build Coastguard Worker    var mystruct = example4.FooObjectBuilder(
927*890232f2SAndroid Build Coastguard Worker        myFoo: example4.FooPropertiesObjectBuilder(a: true, b: false));
928*890232f2SAndroid Build Coastguard Worker    var bytes = mystruct.toBytes();
929*890232f2SAndroid Build Coastguard Worker    var mystruct_read = example4.Foo(bytes);
930*890232f2SAndroid Build Coastguard Worker    expect(mystruct_read.myFoo!.a, true);
931*890232f2SAndroid Build Coastguard Worker    expect(mystruct_read.myFoo!.b, false);
932*890232f2SAndroid Build Coastguard Worker  }
933*890232f2SAndroid Build Coastguard Worker}
934