blob: 8cee6b281d76991ca90448764e1cd4679f7702b3 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5import 'dart:typed_data';
6import 'dart:io' as io;
7
8import 'package:path/path.dart' as path;
9
10import 'package:flat_buffers/flat_buffers.dart';
11import 'package:test/test.dart';
12import 'package:test_reflective_loader/test_reflective_loader.dart';
13
14import './monster_test_my_game.example_generated.dart' as example;
James Kuszmaul8e62b022022-03-22 09:33:25 -070015import './monster_test_my_game.example2_generated.dart' as example2;
Austin Schuhe89fa2d2019-08-14 20:24:23 -070016
17main() {
18 defineReflectiveSuite(() {
19 defineReflectiveTests(BuilderTest);
James Kuszmaul8e62b022022-03-22 09:33:25 -070020 defineReflectiveTests(ObjectAPITest);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070021 defineReflectiveTests(CheckOtherLangaugesData);
Austin Schuh272c6132020-11-14 16:37:52 -080022 defineReflectiveTests(GeneratorTest);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070023 });
24}
25
26int indexToField(int index) {
27 return (1 + 1 + index) * 2;
28}
29
30@reflectiveTest
31class CheckOtherLangaugesData {
32 test_cppData() async {
James Kuszmaul8e62b022022-03-22 09:33:25 -070033 List<int> data = await io.File(path.join(
34 path.context.current,
35 'test',
Austin Schuhe89fa2d2019-08-14 20:24:23 -070036 'monsterdata_test.mon',
Austin Schuh272c6132020-11-14 16:37:52 -080037 )).readAsBytes();
James Kuszmaul8e62b022022-03-22 09:33:25 -070038 example.Monster mon = example.Monster(data);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070039 expect(mon.hp, 80);
40 expect(mon.mana, 150);
41 expect(mon.name, 'MyMonster');
James Kuszmaul8e62b022022-03-22 09:33:25 -070042 expect(mon.pos!.x, 1.0);
43 expect(mon.pos!.y, 2.0);
44 expect(mon.pos!.z, 3.0);
45 expect(mon.pos!.test1, 3.0);
46 expect(mon.pos!.test2.value, 2.0);
47 expect(mon.pos!.test3.a, 5);
48 expect(mon.pos!.test3.b, 6);
49 expect(mon.testType!.value, example.AnyTypeId.Monster.value);
Austin Schuhe89fa2d2019-08-14 20:24:23 -070050 expect(mon.test is example.Monster, true);
51 final monster2 = mon.test as example.Monster;
52 expect(monster2.name, "Fred");
53
James Kuszmaul8e62b022022-03-22 09:33:25 -070054 expect(mon.inventory!.length, 5);
55 expect(mon.inventory!.reduce((cur, next) => cur + next), 10);
56 final test4 = mon.test4!;
57 expect(test4.length, 2);
58 expect(test4[0].a + test4[0].b + test4[1].a + test4[1].b, 100);
59 expect(mon.testarrayofstring!.length, 2);
60 expect(mon.testarrayofstring![0], "test1");
61 expect(mon.testarrayofstring![1], "test2");
Austin Schuhe89fa2d2019-08-14 20:24:23 -070062
63 // this will fail if accessing any field fails.
Austin Schuh272c6132020-11-14 16:37:52 -080064 expect(
65 mon.toString(),
66 'Monster{'
67 '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 'mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], '
69 'color: Color{value: 8}, testType: AnyTypeId{value: 1}, '
70 'test: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
James Kuszmaul8e62b022022-03-22 09:33:25 -070071 'inventory: null, color: Color{value: 8}, testType: null, '
Austin Schuh272c6132020-11-14 16:37:52 -080072 'test: null, test4: null, testarrayofstring: null, '
73 'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
74 'testempty: null, testbool: false, testhashs32Fnv1: 0, '
75 'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
76 'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
77 'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
78 'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
79 'testarrayofsortedstruct: null, flex: null, test5: null, '
80 'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
81 'vectorOfReferrables: null, singleWeakReference: 0, '
82 'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
83 'coOwningReference: 0, vectorOfCoOwningReferences: null, '
84 'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
James Kuszmaul8e62b022022-03-22 09:33:25 -070085 'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
86 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
87 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
88 'nativeInline: null, '
89 'longEnumNonEnumDefault: LongEnum{value: 0}, '
90 'longEnumNormalDefault: LongEnum{value: 2}}, '
Austin Schuh272c6132020-11-14 16:37:52 -080091 'test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
92 'testarrayofstring: [test1, test2], testarrayoftables: null, '
93 'enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, '
James Kuszmaul8e62b022022-03-22 09:33:25 -070094 'inventory: null, color: Color{value: 8}, testType: null, '
Austin Schuh272c6132020-11-14 16:37:52 -080095 'test: null, test4: null, testarrayofstring: null, '
96 'testarrayoftables: null, enemy: null, testnestedflatbuffer: null, '
97 'testempty: null, testbool: false, testhashs32Fnv1: 0, '
98 'testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, '
99 'testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, '
100 'testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, '
101 'testf2: 3.0, testf3: 0.0, testarrayofstring2: null, '
102 'testarrayofsortedstruct: null, flex: null, test5: null, '
103 'vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, '
104 'vectorOfReferrables: null, singleWeakReference: 0, '
105 'vectorOfWeakReferences: null, vectorOfStrongReferrables: null, '
106 'coOwningReference: 0, vectorOfCoOwningReferences: null, '
107 'nonOwningReference: 0, vectorOfNonOwningReferences: null, '
James Kuszmaul8e62b022022-03-22 09:33:25 -0700108 'anyUniqueType: null, anyUnique: null, anyAmbiguousType: null, '
109 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
110 'testrequirednestedflatbuffer: null, scalarKeySortedTables: null, '
111 'nativeInline: null, '
112 'longEnumNonEnumDefault: LongEnum{value: 0}, '
113 'longEnumNormalDefault: LongEnum{value: 2}}, '
Austin Schuh272c6132020-11-14 16:37:52 -0800114 'testnestedflatbuffer: null, testempty: null, testbool: true, '
115 'testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, '
116 'testhashs64Fnv1: 7930699090847568257, '
117 'testhashu64Fnv1: 7930699090847568257, '
118 'testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, '
119 'testhashs64Fnv1a: 4898026182817603057, '
120 'testhashu64Fnv1a: 4898026182817603057, '
121 'testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, '
James Kuszmaul8e62b022022-03-22 09:33:25 -0700122 'testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: ['
123 'Ability{id: 0, distance: 45}, Ability{id: 1, distance: 21}, '
124 'Ability{id: 5, distance: 12}], '
Austin Schuh272c6132020-11-14 16:37:52 -0800125 'flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], '
126 'vectorOfLongs: [1, 100, 10000, 1000000, 100000000], '
127 'vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], '
128 'parentNamespaceTest: null, vectorOfReferrables: null, '
129 'singleWeakReference: 0, vectorOfWeakReferences: null, '
130 'vectorOfStrongReferrables: null, coOwningReference: 0, '
131 'vectorOfCoOwningReferences: null, nonOwningReference: 0, '
132 'vectorOfNonOwningReferences: null, '
James Kuszmaul8e62b022022-03-22 09:33:25 -0700133 'anyUniqueType: null, anyUnique: null, '
134 'anyAmbiguousType: null, '
135 'anyAmbiguous: null, vectorOfEnums: null, signedEnum: Race{value: -1}, '
136 'testrequirednestedflatbuffer: null, scalarKeySortedTables: [Stat{id: '
137 'miss, val: 0, count: 0}, Stat{id: hit, val: 10, count: 1}], '
138 'nativeInline: Test{a: 1, b: 2}, '
139 'longEnumNonEnumDefault: LongEnum{value: 0}, '
140 'longEnumNormalDefault: LongEnum{value: 2}}',
Austin Schuh272c6132020-11-14 16:37:52 -0800141 );
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700142 }
143}
144
James Kuszmaul8e62b022022-03-22 09:33:25 -0700145/// Test a custom, fixed-memory allocator (no actual allocations performed)
146class CustomAllocator extends Allocator {
147 final _memory = ByteData(10 * 1024);
148 int _used = 0;
149
150 Uint8List buffer(int size) => _memory.buffer.asUint8List(_used - size, size);
151
152 @override
153 ByteData allocate(int size) {
154 if (size > _memory.lengthInBytes) {
155 throw UnsupportedError('Trying to allocate too much');
156 }
157 _used = size;
158 return ByteData.sublistView(_memory, 0, size);
159 }
160
161 @override
162 void deallocate(ByteData _) {}
163}
164
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700165@reflectiveTest
166class BuilderTest {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700167 void test_monsterBuilder([Builder? builder]) {
168 final fbBuilder = builder ?? Builder();
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700169 final str = fbBuilder.writeString('MyMonster');
170
171 fbBuilder.writeString('test1');
James Kuszmaul8e62b022022-03-22 09:33:25 -0700172 fbBuilder.writeString('test2', asciiOptimization: true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700173 final testArrayOfString = fbBuilder.endStructVector(2);
174
175 final fred = fbBuilder.writeString('Fred');
176
177 final List<int> treasure = [0, 1, 2, 3, 4];
178 final inventory = fbBuilder.writeListUint8(treasure);
179
James Kuszmaul8e62b022022-03-22 09:33:25 -0700180 final monBuilder = example.MonsterBuilder(fbBuilder)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700181 ..begin()
182 ..addNameOffset(fred);
183 final mon2 = monBuilder.finish();
184
James Kuszmaul8e62b022022-03-22 09:33:25 -0700185 final testBuilder = example.TestBuilder(fbBuilder);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700186 testBuilder.finish(10, 20);
187 testBuilder.finish(30, 40);
188 final test4 = fbBuilder.endStructVector(2);
189
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700190 monBuilder
191 ..begin()
192 ..addPos(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700193 example.Vec3Builder(fbBuilder).finish(
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700194 1.0,
195 2.0,
196 3.0,
197 3.0,
198 example.Color.Green,
199 () => testBuilder.finish(5, 6),
200 ),
201 )
202 ..addHp(80)
203 ..addNameOffset(str)
204 ..addInventoryOffset(inventory)
205 ..addTestType(example.AnyTypeId.Monster)
206 ..addTestOffset(mon2)
207 ..addTest4Offset(test4)
208 ..addTestarrayofstringOffset(testArrayOfString);
209 final mon = monBuilder.finish();
210 fbBuilder.finish(mon);
211 }
212
James Kuszmaul8e62b022022-03-22 09:33:25 -0700213 void test_error_addInt32_withoutStartTable([Builder? builder]) {
214 builder ??= Builder();
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700215 expect(() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700216 builder!.addInt32(0, 0);
217 }, throwsA(isA<AssertionError>()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700218 }
219
220 void test_error_addOffset_withoutStartTable() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700221 Builder builder = Builder();
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700222 expect(() {
223 builder.addOffset(0, 0);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700224 }, throwsA(isA<AssertionError>()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700225 }
226
227 void test_error_endTable_withoutStartTable() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700228 Builder builder = Builder();
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700229 expect(() {
230 builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700231 }, throwsA(isA<AssertionError>()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700232 }
233
234 void test_error_startTable_duringTable() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700235 Builder builder = Builder();
236 builder.startTable(0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700237 expect(() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700238 builder.startTable(0);
239 }, throwsA(isA<AssertionError>()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700240 }
241
242 void test_error_writeString_duringTable() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700243 Builder builder = Builder();
244 builder.startTable(1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700245 expect(() {
246 builder.writeString('12345');
James Kuszmaul8e62b022022-03-22 09:33:25 -0700247 }, throwsA(isA<AssertionError>()));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700248 }
249
250 void test_file_identifier() {
251 Uint8List byteList;
252 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700253 Builder builder = Builder(initialSize: 0);
254 builder.startTable(0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700255 int offset = builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700256 builder.finish(offset, 'Az~ÿ');
257 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700258 }
259 // Convert byteList to a ByteData so that we can read data from it.
260 ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
261 // First 4 bytes are an offset to the table data.
262 int tableDataLoc = byteData.getUint32(0, Endian.little);
263 // Next 4 bytes are the file identifier.
264 expect(byteData.getUint8(4), 65); // 'a'
265 expect(byteData.getUint8(5), 122); // 'z'
266 expect(byteData.getUint8(6), 126); // '~'
267 expect(byteData.getUint8(7), 255); // 'ÿ'
268 // First 4 bytes of the table data are a backwards offset to the vtable.
Austin Schuh272c6132020-11-14 16:37:52 -0800269 int vTableLoc =
270 tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700271 // First 2 bytes of the vtable are the size of the vtable in bytes, which
272 // should be 4.
273 expect(byteData.getUint16(vTableLoc, Endian.little), 4);
274 // Next 2 bytes are the size of the object in bytes (including the vtable
275 // pointer), which should be 4.
276 expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
277 }
278
279 void test_low() {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700280 final allocator = CustomAllocator();
281 final builder = Builder(initialSize: 0, allocator: allocator);
282
283 builder.putUint8(1);
284 expect(allocator.buffer(builder.size()), [1]);
285
286 builder.putUint32(2);
287 expect(allocator.buffer(builder.size()), [2, 0, 0, 0, 0, 0, 0, 1]);
288
289 builder.putUint8(3);
290 expect(
291 allocator.buffer(builder.size()), [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
292
293 builder.putUint8(4);
294 expect(
295 allocator.buffer(builder.size()), [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
296
297 builder.putUint8(5);
298 expect(
299 allocator.buffer(builder.size()), [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
300
301 builder.putUint32(6);
302 expect(allocator.buffer(builder.size()),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700303 [6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
304 }
305
306 void test_table_default() {
307 List<int> byteList;
308 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700309 final builder = Builder(initialSize: 0, allocator: CustomAllocator());
310 builder.startTable(2);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700311 builder.addInt32(0, 10, 10);
312 builder.addInt32(1, 20, 10);
313 int offset = builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700314 builder.finish(offset);
315 byteList = builder.buffer;
316 expect(builder.size(), byteList.length);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700317 }
318 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700319 BufferContext buffer = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700320 int objectOffset = buffer.derefObject(0);
321 // was not written, so uses the new default value
322 expect(
323 const Int32Reader()
324 .vTableGet(buffer, objectOffset, indexToField(0), 15),
325 15);
326 // has the written value
327 expect(
328 const Int32Reader()
329 .vTableGet(buffer, objectOffset, indexToField(1), 15),
330 20);
331 }
332
James Kuszmaul8e62b022022-03-22 09:33:25 -0700333 void test_table_format([Builder? builder]) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700334 Uint8List byteList;
335 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700336 builder ??= Builder(initialSize: 0);
337 builder.startTable(3);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700338 builder.addInt32(0, 10);
339 builder.addInt32(1, 20);
340 builder.addInt32(2, 30);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700341 builder.finish(builder.endTable());
342 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700343 }
344 // Convert byteList to a ByteData so that we can read data from it.
345 ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
346 // First 4 bytes are an offset to the table data.
347 int tableDataLoc = byteData.getUint32(0, Endian.little);
348 // First 4 bytes of the table data are a backwards offset to the vtable.
Austin Schuh272c6132020-11-14 16:37:52 -0800349 int vTableLoc =
350 tableDataLoc - byteData.getInt32(tableDataLoc, Endian.little);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700351 // First 2 bytes of the vtable are the size of the vtable in bytes, which
352 // should be 10.
353 expect(byteData.getUint16(vTableLoc, Endian.little), 10);
354 // Next 2 bytes are the size of the object in bytes (including the vtable
355 // pointer), which should be 16.
356 expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
357 // Remaining 6 bytes are the offsets within the object where the ints are
358 // located.
359 for (int i = 0; i < 3; i++) {
Austin Schuh272c6132020-11-14 16:37:52 -0800360 int offset = byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
361 expect(
362 byteData.getInt32(tableDataLoc + offset, Endian.little), 10 + 10 * i);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700363 }
364 }
365
366 void test_table_string() {
367 String latinString = 'test';
368 String unicodeString = 'Проба пера';
369 List<int> byteList;
370 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700371 Builder builder = Builder(initialSize: 0);
372 int? latinStringOffset =
373 builder.writeString(latinString, asciiOptimization: true);
374 int? unicodeStringOffset =
375 builder.writeString(unicodeString, asciiOptimization: true);
376 builder.startTable(2);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700377 builder.addOffset(0, latinStringOffset);
378 builder.addOffset(1, unicodeStringOffset);
379 int offset = builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700380 builder.finish(offset);
381 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700382 }
383 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700384 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700385 int objectOffset = buf.derefObject(0);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700386 expect(
387 const StringReader()
388 .vTableGetNullable(buf, objectOffset, indexToField(0)),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700389 latinString);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700390 expect(
391 const StringReader(asciiOptimization: true)
392 .vTableGetNullable(buf, objectOffset, indexToField(1)),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700393 unicodeString);
394 }
395
James Kuszmaul8e62b022022-03-22 09:33:25 -0700396 void test_table_types([Builder? builder]) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700397 List<int> byteList;
398 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700399 builder ??= Builder(initialSize: 0);
400 int? stringOffset = builder.writeString('12345');
401 builder.startTable(7);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700402 builder.addBool(0, true);
403 builder.addInt8(1, 10);
404 builder.addInt32(2, 20);
405 builder.addOffset(3, stringOffset);
406 builder.addInt32(4, 40);
407 builder.addUint32(5, 0x9ABCDEF0);
408 builder.addUint8(6, 0x9A);
409 int offset = builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700410 builder.finish(offset);
411 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700412 }
413 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700414 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700415 int objectOffset = buf.derefObject(0);
416 expect(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700417 const BoolReader()
418 .vTableGetNullable(buf, objectOffset, indexToField(0)),
419 true);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700420 expect(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700421 const Int8Reader()
422 .vTableGetNullable(buf, objectOffset, indexToField(1)),
423 10);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700424 expect(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700425 const Int32Reader()
426 .vTableGetNullable(buf, objectOffset, indexToField(2)),
427 20);
428 expect(
429 const StringReader()
430 .vTableGetNullable(buf, objectOffset, indexToField(3)),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700431 '12345');
432 expect(
James Kuszmaul8e62b022022-03-22 09:33:25 -0700433 const Int32Reader()
434 .vTableGetNullable(buf, objectOffset, indexToField(4)),
435 40);
436 expect(
437 const Uint32Reader()
438 .vTableGetNullable(buf, objectOffset, indexToField(5)),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700439 0x9ABCDEF0);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700440 expect(
441 const Uint8Reader()
442 .vTableGetNullable(buf, objectOffset, indexToField(6)),
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700443 0x9A);
444 }
445
446 void test_writeList_of_Uint32() {
447 List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
448 // write
449 List<int> byteList;
450 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700451 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700452 int offset = builder.writeListUint32(values);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700453 builder.finish(offset);
454 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700455 }
456 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700457 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700458 List<int> items = const Uint32ListReader().read(buf, 0);
459 expect(items, hasLength(4));
460 expect(items, orderedEquals(values));
461 }
462
463 void test_writeList_ofBool() {
464 void verifyListBooleans(int len, List<int> trueBits) {
465 // write
466 List<int> byteList;
467 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700468 Builder builder = Builder(initialSize: 0);
469 List<bool> values = List<bool>.filled(len, false);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700470 for (int bit in trueBits) {
471 values[bit] = true;
472 }
473 int offset = builder.writeListBool(values);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700474 builder.finish(offset);
475 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700476 }
477 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700478 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700479 List<bool> items = const BoolListReader().read(buf, 0);
480 expect(items, hasLength(len));
481 for (int i = 0; i < items.length; i++) {
482 expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
483 }
484 }
485
486 verifyListBooleans(0, <int>[]);
487 verifyListBooleans(1, <int>[]);
488 verifyListBooleans(1, <int>[0]);
489 verifyListBooleans(31, <int>[0, 1]);
490 verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
491 verifyListBooleans(31, <int>[0, 30]);
492 verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
493 verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
494 verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
495 verifyListBooleans(63, <int>[]);
496 verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700497 verifyListBooleans(63, List<int>.generate(63, (i) => i));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700498 verifyListBooleans(64, <int>[]);
499 verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
500 verifyListBooleans(64, <int>[1, 2, 62]);
501 verifyListBooleans(64, <int>[0, 1, 2, 63]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700502 verifyListBooleans(64, List<int>.generate(64, (i) => i));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700503 verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
504 }
505
506 void test_writeList_ofInt32() {
507 List<int> byteList;
508 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700509 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700510 int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700511 builder.finish(offset);
512 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700513 }
514 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700515 BufferContext buf = BufferContext.fromBytes(byteList);
516 List<int> items = const ListReader<int>(Int32Reader()).read(buf, 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700517 expect(items, hasLength(5));
518 expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
519 }
520
521 void test_writeList_ofFloat64() {
522 List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
523 // write
524 List<int> byteList;
525 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700526 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700527 int offset = builder.writeListFloat64(values);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700528 builder.finish(offset);
529 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700530 }
531
532 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700533 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700534 List<double> items = const Float64ListReader().read(buf, 0);
535
536 expect(items, hasLength(values.length));
537 for (int i = 0; i < values.length; i++) {
538 expect(values[i], closeTo(items[i], .001));
539 }
540 }
541
542 void test_writeList_ofFloat32() {
543 List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
544 // write
545 List<int> byteList;
546 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700547 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700548 int offset = builder.writeListFloat32(values);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700549 builder.finish(offset);
550 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700551 }
552 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700553 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700554 List<double> items = const Float32ListReader().read(buf, 0);
555 expect(items, hasLength(5));
556 for (int i = 0; i < values.length; i++) {
557 expect(values[i], closeTo(items[i], .001));
558 }
559 }
560
James Kuszmaul8e62b022022-03-22 09:33:25 -0700561 void test_writeList_ofObjects([Builder? builder]) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700562 List<int> byteList;
563 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700564 builder ??= Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700565 // write the object #1
566 int object1;
567 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700568 builder.startTable(2);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700569 builder.addInt32(0, 10);
570 builder.addInt32(1, 20);
571 object1 = builder.endTable();
572 }
573 // write the object #1
574 int object2;
575 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700576 builder.startTable(2);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700577 builder.addInt32(0, 100);
578 builder.addInt32(1, 200);
579 object2 = builder.endTable();
580 }
581 // write the list
582 int offset = builder.writeList([object1, object2]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700583 builder.finish(offset);
584 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700585 }
586 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700587 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700588 List<TestPointImpl> items =
James Kuszmaul8e62b022022-03-22 09:33:25 -0700589 const ListReader<TestPointImpl>(TestPointReader()).read(buf, 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700590 expect(items, hasLength(2));
591 expect(items[0].x, 10);
592 expect(items[0].y, 20);
593 expect(items[1].x, 100);
594 expect(items[1].y, 200);
595 }
596
597 void test_writeList_ofStrings_asRoot() {
598 List<int> byteList;
599 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700600 Builder builder = Builder(initialSize: 0);
601 int? str1 = builder.writeString('12345');
602 int? str2 = builder.writeString('ABC');
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700603 int offset = builder.writeList([str1, str2]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700604 builder.finish(offset);
605 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700606 }
607 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700608 BufferContext buf = BufferContext.fromBytes(byteList);
609 List<String> items = const ListReader<String>(StringReader()).read(buf, 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700610 expect(items, hasLength(2));
611 expect(items, contains('12345'));
612 expect(items, contains('ABC'));
613 }
614
James Kuszmaul8e62b022022-03-22 09:33:25 -0700615 void test_writeList_ofStrings_inObject([Builder? builder]) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700616 List<int> byteList;
617 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700618 builder ??= Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700619 int listOffset = builder.writeList(
620 [builder.writeString('12345'), builder.writeString('ABC')]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700621 builder.startTable(1);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700622 builder.addOffset(0, listOffset);
623 int offset = builder.endTable();
James Kuszmaul8e62b022022-03-22 09:33:25 -0700624 builder.finish(offset);
625 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700626 }
627 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700628 BufferContext buf = BufferContext.fromBytes(byteList);
629 StringListWrapperImpl reader = StringListWrapperReader().read(buf, 0);
630 List<String>? items = reader.items;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700631 expect(items, hasLength(2));
632 expect(items, contains('12345'));
633 expect(items, contains('ABC'));
634 }
635
636 void test_writeList_ofUint32() {
637 List<int> byteList;
638 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700639 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700640 int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700641 builder.finish(offset);
642 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700643 }
644 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700645 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700646 List<int> items = const Uint32ListReader().read(buf, 0);
647 expect(items, hasLength(3));
648 expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
649 }
650
651 void test_writeList_ofUint16() {
652 List<int> byteList;
653 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700654 Builder builder = Builder(initialSize: 0);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700655 int offset = builder.writeListUint16(<int>[1, 2, 60000]);
James Kuszmaul8e62b022022-03-22 09:33:25 -0700656 builder.finish(offset);
657 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700658 }
659 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700660 BufferContext buf = BufferContext.fromBytes(byteList);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700661 List<int> items = const Uint16ListReader().read(buf, 0);
662 expect(items, hasLength(3));
663 expect(items, orderedEquals(<int>[1, 2, 60000]));
664 }
665
666 void test_writeList_ofUint8() {
667 List<int> byteList;
668 {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700669 Builder builder = Builder(initialSize: 0);
670 int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A, 0xFA]);
671 builder.finish(offset);
672 byteList = builder.buffer;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700673 }
674 // read and verify
James Kuszmaul8e62b022022-03-22 09:33:25 -0700675 BufferContext buf = BufferContext.fromBytes(byteList);
676 const buffOffset = 8; // 32-bit offset to the list, + 32-bit length
677 for (final lazy in [true, false]) {
678 List<int> items = Uint8ListReader(lazy: lazy).read(buf, 0);
679 expect(items, hasLength(6));
680 expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A, 0xFA]));
681
682 // overwrite the buffer to verify the laziness
683 buf.buffer.setUint8(buffOffset + 1, 99);
684 expect(items, orderedEquals(<int>[1, lazy ? 99 : 2, 3, 4, 0x9A, 0xFA]));
685
686 // restore the previous value for the next loop
687 buf.buffer.setUint8(buffOffset + 1, 2);
688 }
689 }
690
691 void test_reset() {
692 // We'll run a selection of tests , reusing the builder between them.
693 final testCases = <void Function(Builder?)>[
694 test_monsterBuilder,
695 test_error_addInt32_withoutStartTable,
696 test_table_format,
697 test_table_types,
698 test_writeList_ofObjects,
699 test_writeList_ofStrings_inObject
700 ];
701
702 // Execute all test cases in all permutations of their order.
703 // To do that, we generate permutations of test case indexes.
704 final testCasesPermutations =
705 _permutationsOf(List.generate(testCases.length, (index) => index));
706 expect(testCasesPermutations.length, _factorial(testCases.length));
707
708 for (var indexes in testCasesPermutations) {
709 // print the order so failures are reproducible
710 printOnFailure('Running reset() test cases in order: $indexes');
711
712 Builder? builder;
713 for (var index in indexes) {
714 if (builder == null) {
715 // Initial size small enough so at least one test case increases it.
716 // On the other hand, it's large enough so that some test cases don't.
717 builder = Builder(initialSize: 32);
718 } else {
719 builder.reset();
720 }
721 testCases[index](builder);
722 }
723 }
724 }
725
726 // Generate permutations of the given list
727 List<List<T>> _permutationsOf<T>(List<T> source) {
728 final result = <List<T>>[];
729
730 void permutate(List<T> items, int startAt) {
731 for (var i = startAt; i < items.length; i++) {
732 List<T> permutation = items.toList(growable: false);
733 permutation[i] = items[startAt];
734 permutation[startAt] = items[i];
735
736 // add the current list upon reaching the end
737 if (startAt == items.length - 1) {
738 result.add(items);
739 } else {
740 permutate(permutation, startAt + 1);
741 }
742 }
743 }
744
745 permutate(source, 0);
746 return result;
747 }
748
749 // a very simple implementation of n!
750 int _factorial(int n) {
751 var result = 1;
752 for (var i = 2; i <= n; i++) {
753 result *= i;
754 }
755 return result;
756 }
757}
758
759@reflectiveTest
760class ObjectAPITest {
761 void test_tableStat() {
762 final object1 = example.StatT(count: 3, id: "foo", val: 4);
763 expect(object1 is Packable, isTrue);
764 final fbb = Builder();
765 fbb.finish(object1.pack(fbb));
766 final object2 = example.Stat(fbb.buffer).unpack();
767 expect(object2.count, object1.count);
768 expect(object2.id, object1.id);
769 expect(object2.val, object1.val);
770 expect(object2.toString(), object1.toString());
771 }
772
773 void test_tableMonster() {
774 final monster = example.MonsterT()
775 ..pos = example.Vec3T(
776 x: 1,
777 y: 2,
778 z: 3,
779 test1: 4.0,
780 test2: example.Color.Red,
781 test3: example.TestT(a: 1, b: 2))
782 ..mana = 2
783 ..name = 'Monstrous'
784 ..inventory = [24, 42]
785 ..color = example.Color.Green
786 // TODO be smarter for unions and automatically set the `type` field?
787 ..testType = example.AnyTypeId.MyGame_Example2_Monster
788 ..test = example2.MonsterT()
789 ..test4 = [example.TestT(a: 3, b: 4), example.TestT(a: 5, b: 6)]
790 ..testarrayofstring = ["foo", "bar"]
791 ..testarrayoftables = [example.MonsterT(name: 'Oof')]
792 ..enemy = example.MonsterT(name: 'Enemy')
793 ..testarrayofbools = [false, true, false]
794 ..testf = 42.24
795 ..testarrayofsortedstruct = [
796 example.AbilityT(id: 1, distance: 5),
797 example.AbilityT(id: 3, distance: 7)
798 ]
799 ..vectorOfLongs = [5, 6, 7]
800 ..vectorOfDoubles = [8.9, 9.0, 10.1, 11.2]
801 ..anyAmbiguousType = example.AnyAmbiguousAliasesTypeId.M2
802 ..anyAmbiguous = null
803 ..vectorOfEnums = [example.Color.Blue, example.Color.Green]
804 ..signedEnum = example.Race.None;
805
806 final fbBuilder = Builder();
807 final offset = monster.pack(fbBuilder);
808 expect(offset, isNonZero);
809 fbBuilder.finish(offset);
810 final data = fbBuilder.buffer;
811
812 // TODO currently broken because of struct builder issue, see #6688
813 // final monster2 = example.Monster(data); // Monster (reader)
814 // expect(
815 // // map Monster => MonsterT, Vec3 => Vec3T, ...
816 // monster2.toString().replaceAllMapped(
817 // RegExp('([a-zA-z0-9]+){'), (match) => match.group(1) + 'T{'),
818 // monster.toString());
819 //
820 // final monster3 = monster2.unpack(); // MonsterT
821 // expect(monster3.toString(), monster.toString());
822 }
823
824 void test_Lists() {
825 // Ensure unpack() reads lists eagerly by reusing the same builder and
826 // overwriting data. Why: because standard reader reads lists lazily...
827 final fbb = Builder();
828
829 final object1 = example.TypeAliasesT(v8: [1, 2, 3], vf64: [5, 6]);
830 fbb.finish(object1.pack(fbb));
831 final object1Read = example.TypeAliases(fbb.buffer).unpack();
832
833 // overwrite the original buffer by writing to the same builder
834 fbb.reset();
835 final object2 = example.TypeAliasesT(v8: [7, 8, 9], vf64: [10, 11]);
836 fbb.finish(object2.pack(fbb));
837 final object2Read = example.TypeAliases(fbb.buffer).unpack();
838
839 // this is fine even with lazy lists:
840 expect(object2.toString(), object2Read.toString());
841
842 // this fails with lazy lists:
843 expect(object1.toString(), object1Read.toString());
844
845 // empty list must be serialized as such (were stored NULL before v2.0)
846 fbb.reset();
847 final object3 = example.TypeAliasesT(v8: [], vf64: null);
848 fbb.finish(object3.pack(fbb));
849 final object3Read = example.TypeAliases(fbb.buffer).unpack();
850 expect(object3.toString(), object3Read.toString());
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700851 }
852}
853
854class StringListWrapperImpl {
855 final BufferContext bp;
856 final int offset;
857
858 StringListWrapperImpl(this.bp, this.offset);
859
James Kuszmaul8e62b022022-03-22 09:33:25 -0700860 List<String>? get items => const ListReader<String>(StringReader())
861 .vTableGetNullable(bp, offset, indexToField(0));
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700862}
863
864class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
865 const StringListWrapperReader();
866
867 @override
868 StringListWrapperImpl createObject(BufferContext object, int offset) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700869 return StringListWrapperImpl(object, offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700870 }
871}
872
873class TestPointImpl {
874 final BufferContext bp;
875 final int offset;
876
877 TestPointImpl(this.bp, this.offset);
878
879 int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
880
881 int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
882}
883
884class TestPointReader extends TableReader<TestPointImpl> {
885 const TestPointReader();
886
887 @override
888 TestPointImpl createObject(BufferContext object, int offset) {
James Kuszmaul8e62b022022-03-22 09:33:25 -0700889 return TestPointImpl(object, offset);
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700890 }
891}
Austin Schuh272c6132020-11-14 16:37:52 -0800892
893@reflectiveTest
894class GeneratorTest {
895 void test_constantEnumValues() async {
896 expect(example.Color.values, same(example.Color.values));
897 expect(example.Race.values, same(example.Race.values));
898 expect(example.AnyTypeId.values, same(example.AnyTypeId.values));
James Kuszmaul8e62b022022-03-22 09:33:25 -0700899 expect(example.AnyUniqueAliasesTypeId.values,
900 same(example.AnyUniqueAliasesTypeId.values));
901 expect(example.AnyAmbiguousAliasesTypeId.values,
902 same(example.AnyAmbiguousAliasesTypeId.values));
Austin Schuh272c6132020-11-14 16:37:52 -0800903 }
904}