Home | History | Annotate | Download | only in test
      1 // 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 
      5 import 'dart:typed_data';
      6 import 'dart:io' as io;
      7 
      8 import 'package:path/path.dart' as path;
      9 
     10 import 'package:flat_buffers/flat_buffers.dart';
     11 import 'package:test/test.dart';
     12 import 'package:test_reflective_loader/test_reflective_loader.dart';
     13 
     14 import './monster_test_my_game.example_generated.dart' as example;
     15 
     16 main() {
     17   defineReflectiveSuite(() {
     18     defineReflectiveTests(BuilderTest);
     19     defineReflectiveTests(CheckOtherLangaugesData);
     20   });
     21 }
     22 
     23 int indexToField(int index) {
     24   return (1 + 1 + index) * 2;
     25 }
     26 
     27 @reflectiveTest
     28 class CheckOtherLangaugesData {
     29   test_cppData() async {
     30     List<int> data = await new io.File(path.join(
     31       path.dirname(io.Platform.script.path),
     32       'monsterdata_test.mon',
     33     ))
     34         .readAsBytes();
     35     example.Monster mon = new example.Monster(data);
     36     expect(mon.hp, 80);
     37     expect(mon.mana, 150);
     38     expect(mon.name, 'MyMonster');
     39     expect(mon.pos.x, 1.0);
     40     expect(mon.pos.y, 2.0);
     41     expect(mon.pos.z, 3.0);
     42     expect(mon.pos.test1, 3.0);
     43     expect(mon.pos.test2.value, 2.0);
     44     expect(mon.pos.test3.a, 5);
     45     expect(mon.pos.test3.b, 6);
     46     expect(mon.testType.value, example.AnyTypeId.Monster.value);
     47     expect(mon.test is example.Monster, true);
     48     final monster2 = mon.test as example.Monster;
     49     expect(monster2.name, "Fred");
     50 
     51     expect(mon.inventory.length, 5);
     52     expect(mon.inventory.reduce((cur, next) => cur + next), 10);
     53     expect(mon.test4.length, 2);
     54     expect(
     55         mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100);
     56     expect(mon.testarrayofstring.length, 2);
     57     expect(mon.testarrayofstring[0], "test1");
     58     expect(mon.testarrayofstring[1], "test2");
     59 
     60     // this will fail if accessing any field fails.
     61     expect(mon.toString(),
     62         'Monster{pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color{value: 2}, test3: Test{a: 5, b: 6}}, mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], color: Color{value: 8}, testType: AnyTypeId{value: 1}, test: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], testarrayofstring: [test1, test2], testarrayoftables: null, enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, testhashs64Fnv1: 7930699090847568257, testhashu64Fnv1: 7930699090847568257, testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, testhashs64Fnv1a: 4898026182817603057, testhashu64Fnv1a: 4898026182817603057, testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], vectorOfLongs: [1, 100, 10000, 1000000, 100000000], vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}');
     63   }
     64 }
     65 
     66 @reflectiveTest
     67 class BuilderTest {
     68   void test_monsterBuilder() {
     69     final fbBuilder = new Builder();
     70     final str = fbBuilder.writeString('MyMonster');
     71 
     72     fbBuilder.writeString('test1');
     73     fbBuilder.writeString('test2');
     74     final testArrayOfString = fbBuilder.endStructVector(2);
     75 
     76     final fred = fbBuilder.writeString('Fred');
     77 
     78     final List<int> treasure = [0, 1, 2, 3, 4];
     79     final inventory = fbBuilder.writeListUint8(treasure);
     80 
     81     final monBuilder = new example.MonsterBuilder(fbBuilder)
     82       ..begin()
     83       ..addNameOffset(fred);
     84     final mon2 = monBuilder.finish();
     85 
     86     final testBuilder = new example.TestBuilder(fbBuilder);
     87     testBuilder.finish(10, 20);
     88     testBuilder.finish(30, 40);
     89     final test4 = fbBuilder.endStructVector(2);
     90 
     91 
     92     monBuilder
     93       ..begin()
     94       ..addPos(
     95         new example.Vec3Builder(fbBuilder).finish(
     96           1.0,
     97           2.0,
     98           3.0,
     99           3.0,
    100           example.Color.Green,
    101           () => testBuilder.finish(5, 6),
    102         ),
    103       )
    104       ..addHp(80)
    105       ..addNameOffset(str)
    106       ..addInventoryOffset(inventory)
    107       ..addTestType(example.AnyTypeId.Monster)
    108       ..addTestOffset(mon2)
    109       ..addTest4Offset(test4)
    110       ..addTestarrayofstringOffset(testArrayOfString);
    111     final mon = monBuilder.finish();
    112     fbBuilder.finish(mon);
    113   }
    114 
    115   void test_error_addInt32_withoutStartTable() {
    116     Builder builder = new Builder();
    117     expect(() {
    118       builder.addInt32(0, 0);
    119     }, throwsStateError);
    120   }
    121 
    122   void test_error_addOffset_withoutStartTable() {
    123     Builder builder = new Builder();
    124     expect(() {
    125       builder.addOffset(0, 0);
    126     }, throwsStateError);
    127   }
    128 
    129   void test_error_endTable_withoutStartTable() {
    130     Builder builder = new Builder();
    131     expect(() {
    132       builder.endTable();
    133     }, throwsStateError);
    134   }
    135 
    136   void test_error_startTable_duringTable() {
    137     Builder builder = new Builder();
    138     builder.startTable();
    139     expect(() {
    140       builder.startTable();
    141     }, throwsStateError);
    142   }
    143 
    144   void test_error_writeString_duringTable() {
    145     Builder builder = new Builder();
    146     builder.startTable();
    147     expect(() {
    148       builder.writeString('12345');
    149     }, throwsStateError);
    150   }
    151 
    152   void test_file_identifier() {
    153     Uint8List byteList;
    154     {
    155       Builder builder = new Builder(initialSize: 0);
    156       builder.startTable();
    157       int offset = builder.endTable();
    158       byteList = builder.finish(offset, 'Az~');
    159     }
    160     // Convert byteList to a ByteData so that we can read data from it.
    161     ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
    162     // First 4 bytes are an offset to the table data.
    163     int tableDataLoc = byteData.getUint32(0, Endian.little);
    164     // Next 4 bytes are the file identifier.
    165     expect(byteData.getUint8(4), 65); // 'a'
    166     expect(byteData.getUint8(5), 122); // 'z'
    167     expect(byteData.getUint8(6), 126); // '~'
    168     expect(byteData.getUint8(7), 255); // ''
    169     // First 4 bytes of the table data are a backwards offset to the vtable.
    170     int vTableLoc = tableDataLoc -
    171         byteData.getInt32(tableDataLoc, Endian.little);
    172     // First 2 bytes of the vtable are the size of the vtable in bytes, which
    173     // should be 4.
    174     expect(byteData.getUint16(vTableLoc, Endian.little), 4);
    175     // Next 2 bytes are the size of the object in bytes (including the vtable
    176     // pointer), which should be 4.
    177     expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
    178   }
    179 
    180   void test_low() {
    181     Builder builder = new Builder(initialSize: 0);
    182     expect((builder..putUint8(1)).lowFinish(), [1]);
    183     expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]);
    184     expect((builder..putUint8(3)).lowFinish(),
    185         [0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
    186     expect((builder..putUint8(4)).lowFinish(),
    187         [0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
    188     expect((builder..putUint8(5)).lowFinish(),
    189         [0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
    190     expect((builder..putUint32(6)).lowFinish(),
    191         [6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
    192   }
    193 
    194   void test_table_default() {
    195     List<int> byteList;
    196     {
    197       Builder builder = new Builder(initialSize: 0);
    198       builder.startTable();
    199       builder.addInt32(0, 10, 10);
    200       builder.addInt32(1, 20, 10);
    201       int offset = builder.endTable();
    202       byteList = builder.finish(offset);
    203     }
    204     // read and verify
    205     BufferContext buffer = new BufferContext.fromBytes(byteList);
    206     int objectOffset = buffer.derefObject(0);
    207     // was not written, so uses the new default value
    208     expect(
    209         const Int32Reader()
    210             .vTableGet(buffer, objectOffset, indexToField(0), 15),
    211         15);
    212     // has the written value
    213     expect(
    214         const Int32Reader()
    215             .vTableGet(buffer, objectOffset, indexToField(1), 15),
    216         20);
    217   }
    218 
    219   void test_table_format() {
    220     Uint8List byteList;
    221     {
    222       Builder builder = new Builder(initialSize: 0);
    223       builder.startTable();
    224       builder.addInt32(0, 10);
    225       builder.addInt32(1, 20);
    226       builder.addInt32(2, 30);
    227       byteList = builder.finish(builder.endTable());
    228     }
    229     // Convert byteList to a ByteData so that we can read data from it.
    230     ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
    231     // First 4 bytes are an offset to the table data.
    232     int tableDataLoc = byteData.getUint32(0, Endian.little);
    233     // First 4 bytes of the table data are a backwards offset to the vtable.
    234     int vTableLoc = tableDataLoc -
    235         byteData.getInt32(tableDataLoc, Endian.little);
    236     // First 2 bytes of the vtable are the size of the vtable in bytes, which
    237     // should be 10.
    238     expect(byteData.getUint16(vTableLoc, Endian.little), 10);
    239     // Next 2 bytes are the size of the object in bytes (including the vtable
    240     // pointer), which should be 16.
    241     expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
    242     // Remaining 6 bytes are the offsets within the object where the ints are
    243     // located.
    244     for (int i = 0; i < 3; i++) {
    245       int offset =
    246           byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
    247       expect(byteData.getInt32(tableDataLoc + offset, Endian.little),
    248           10 + 10 * i);
    249     }
    250   }
    251 
    252   void test_table_string() {
    253     String latinString = 'test';
    254     String unicodeString = ' ';
    255     List<int> byteList;
    256     {
    257       Builder builder = new Builder(initialSize: 0);
    258       int latinStringOffset = builder.writeString(latinString);
    259       int unicodeStringOffset = builder.writeString(unicodeString);
    260       builder.startTable();
    261       builder.addOffset(0, latinStringOffset);
    262       builder.addOffset(1, unicodeStringOffset);
    263       int offset = builder.endTable();
    264       byteList = builder.finish(offset);
    265     }
    266     // read and verify
    267     BufferContext buf = new BufferContext.fromBytes(byteList);
    268     int objectOffset = buf.derefObject(0);
    269     expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)),
    270         latinString);
    271     expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)),
    272         unicodeString);
    273   }
    274 
    275   void test_table_types() {
    276     List<int> byteList;
    277     {
    278       Builder builder = new Builder(initialSize: 0);
    279       int stringOffset = builder.writeString('12345');
    280       builder.startTable();
    281       builder.addBool(0, true);
    282       builder.addInt8(1, 10);
    283       builder.addInt32(2, 20);
    284       builder.addOffset(3, stringOffset);
    285       builder.addInt32(4, 40);
    286       builder.addUint32(5, 0x9ABCDEF0);
    287       builder.addUint8(6, 0x9A);
    288       int offset = builder.endTable();
    289       byteList = builder.finish(offset);
    290     }
    291     // read and verify
    292     BufferContext buf = new BufferContext.fromBytes(byteList);
    293     int objectOffset = buf.derefObject(0);
    294     expect(
    295         const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true);
    296     expect(
    297         const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10);
    298     expect(
    299         const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20);
    300     expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)),
    301         '12345');
    302     expect(
    303         const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40);
    304     expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)),
    305         0x9ABCDEF0);
    306     expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)),
    307         0x9A);
    308   }
    309 
    310   void test_writeList_of_Uint32() {
    311     List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
    312     // write
    313     List<int> byteList;
    314     {
    315       Builder builder = new Builder(initialSize: 0);
    316       int offset = builder.writeListUint32(values);
    317       byteList = builder.finish(offset);
    318     }
    319     // read and verify
    320     BufferContext buf = new BufferContext.fromBytes(byteList);
    321     List<int> items = const Uint32ListReader().read(buf, 0);
    322     expect(items, hasLength(4));
    323     expect(items, orderedEquals(values));
    324   }
    325 
    326   void test_writeList_ofBool() {
    327     void verifyListBooleans(int len, List<int> trueBits) {
    328       // write
    329       List<int> byteList;
    330       {
    331         Builder builder = new Builder(initialSize: 0);
    332         List<bool> values = new List<bool>.filled(len, false);
    333         for (int bit in trueBits) {
    334           values[bit] = true;
    335         }
    336         int offset = builder.writeListBool(values);
    337         byteList = builder.finish(offset);
    338       }
    339       // read and verify
    340       BufferContext buf = new BufferContext.fromBytes(byteList);
    341       List<bool> items = const BoolListReader().read(buf, 0);
    342       expect(items, hasLength(len));
    343       for (int i = 0; i < items.length; i++) {
    344         expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
    345       }
    346     }
    347 
    348     verifyListBooleans(0, <int>[]);
    349     verifyListBooleans(1, <int>[]);
    350     verifyListBooleans(1, <int>[0]);
    351     verifyListBooleans(31, <int>[0, 1]);
    352     verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
    353     verifyListBooleans(31, <int>[0, 30]);
    354     verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
    355     verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
    356     verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
    357     verifyListBooleans(63, <int>[]);
    358     verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
    359     verifyListBooleans(63, new List<int>.generate(63, (i) => i));
    360     verifyListBooleans(64, <int>[]);
    361     verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
    362     verifyListBooleans(64, <int>[1, 2, 62]);
    363     verifyListBooleans(64, <int>[0, 1, 2, 63]);
    364     verifyListBooleans(64, new List<int>.generate(64, (i) => i));
    365     verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
    366   }
    367 
    368   void test_writeList_ofInt32() {
    369     List<int> byteList;
    370     {
    371       Builder builder = new Builder(initialSize: 0);
    372       int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
    373       byteList = builder.finish(offset);
    374     }
    375     // read and verify
    376     BufferContext buf = new BufferContext.fromBytes(byteList);
    377     List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0);
    378     expect(items, hasLength(5));
    379     expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
    380   }
    381 
    382   void test_writeList_ofFloat64() {
    383     List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
    384     // write
    385     List<int> byteList;
    386     {
    387       Builder builder = new Builder(initialSize: 0);
    388       int offset = builder.writeListFloat64(values);
    389       byteList = builder.finish(offset);
    390     }
    391 
    392     // read and verify
    393     BufferContext buf = new BufferContext.fromBytes(byteList);
    394     List<double> items = const Float64ListReader().read(buf, 0);
    395 
    396     expect(items, hasLength(values.length));
    397     for (int i = 0; i < values.length; i++) {
    398       expect(values[i], closeTo(items[i], .001));
    399     }
    400   }
    401 
    402   void test_writeList_ofFloat32() {
    403     List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
    404     // write
    405     List<int> byteList;
    406     {
    407       Builder builder = new Builder(initialSize: 0);
    408       int offset = builder.writeListFloat32(values);
    409       byteList = builder.finish(offset);
    410     }
    411     // read and verify
    412     BufferContext buf = new BufferContext.fromBytes(byteList);
    413     List<double> items = const Float32ListReader().read(buf, 0);
    414     expect(items, hasLength(5));
    415     for (int i = 0; i < values.length; i++) {
    416       expect(values[i], closeTo(items[i], .001));
    417     }
    418   }
    419 
    420   void test_writeList_ofObjects() {
    421     List<int> byteList;
    422     {
    423       Builder builder = new Builder(initialSize: 0);
    424       // write the object #1
    425       int object1;
    426       {
    427         builder.startTable();
    428         builder.addInt32(0, 10);
    429         builder.addInt32(1, 20);
    430         object1 = builder.endTable();
    431       }
    432       // write the object #1
    433       int object2;
    434       {
    435         builder.startTable();
    436         builder.addInt32(0, 100);
    437         builder.addInt32(1, 200);
    438         object2 = builder.endTable();
    439       }
    440       // write the list
    441       int offset = builder.writeList([object1, object2]);
    442       byteList = builder.finish(offset);
    443     }
    444     // read and verify
    445     BufferContext buf = new BufferContext.fromBytes(byteList);
    446     List<TestPointImpl> items =
    447         const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0);
    448     expect(items, hasLength(2));
    449     expect(items[0].x, 10);
    450     expect(items[0].y, 20);
    451     expect(items[1].x, 100);
    452     expect(items[1].y, 200);
    453   }
    454 
    455   void test_writeList_ofStrings_asRoot() {
    456     List<int> byteList;
    457     {
    458       Builder builder = new Builder(initialSize: 0);
    459       int str1 = builder.writeString('12345');
    460       int str2 = builder.writeString('ABC');
    461       int offset = builder.writeList([str1, str2]);
    462       byteList = builder.finish(offset);
    463     }
    464     // read and verify
    465     BufferContext buf = new BufferContext.fromBytes(byteList);
    466     List<String> items =
    467         const ListReader<String>(const StringReader()).read(buf, 0);
    468     expect(items, hasLength(2));
    469     expect(items, contains('12345'));
    470     expect(items, contains('ABC'));
    471   }
    472 
    473   void test_writeList_ofStrings_inObject() {
    474     List<int> byteList;
    475     {
    476       Builder builder = new Builder(initialSize: 0);
    477       int listOffset = builder.writeList(
    478           [builder.writeString('12345'), builder.writeString('ABC')]);
    479       builder.startTable();
    480       builder.addOffset(0, listOffset);
    481       int offset = builder.endTable();
    482       byteList = builder.finish(offset);
    483     }
    484     // read and verify
    485     BufferContext buf = new BufferContext.fromBytes(byteList);
    486     StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0);
    487     List<String> items = reader.items;
    488     expect(items, hasLength(2));
    489     expect(items, contains('12345'));
    490     expect(items, contains('ABC'));
    491   }
    492 
    493   void test_writeList_ofUint32() {
    494     List<int> byteList;
    495     {
    496       Builder builder = new Builder(initialSize: 0);
    497       int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
    498       byteList = builder.finish(offset);
    499     }
    500     // read and verify
    501     BufferContext buf = new BufferContext.fromBytes(byteList);
    502     List<int> items = const Uint32ListReader().read(buf, 0);
    503     expect(items, hasLength(3));
    504     expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
    505   }
    506 
    507   void test_writeList_ofUint16() {
    508     List<int> byteList;
    509     {
    510       Builder builder = new Builder(initialSize: 0);
    511       int offset = builder.writeListUint16(<int>[1, 2, 60000]);
    512       byteList = builder.finish(offset);
    513     }
    514     // read and verify
    515     BufferContext buf = new BufferContext.fromBytes(byteList);
    516     List<int> items = const Uint16ListReader().read(buf, 0);
    517     expect(items, hasLength(3));
    518     expect(items, orderedEquals(<int>[1, 2, 60000]));
    519   }
    520 
    521   void test_writeList_ofUint8() {
    522     List<int> byteList;
    523     {
    524       Builder builder = new Builder(initialSize: 0);
    525       int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]);
    526       byteList = builder.finish(offset);
    527     }
    528     // read and verify
    529     BufferContext buf = new BufferContext.fromBytes(byteList);
    530     List<int> items = const Uint8ListReader().read(buf, 0);
    531     expect(items, hasLength(5));
    532     expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A]));
    533   }
    534 }
    535 
    536 class StringListWrapperImpl {
    537   final BufferContext bp;
    538   final int offset;
    539 
    540   StringListWrapperImpl(this.bp, this.offset);
    541 
    542   List<String> get items => const ListReader<String>(const StringReader())
    543       .vTableGet(bp, offset, indexToField(0));
    544 }
    545 
    546 class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
    547   const StringListWrapperReader();
    548 
    549   @override
    550   StringListWrapperImpl createObject(BufferContext object, int offset) {
    551     return new StringListWrapperImpl(object, offset);
    552   }
    553 }
    554 
    555 class TestPointImpl {
    556   final BufferContext bp;
    557   final int offset;
    558 
    559   TestPointImpl(this.bp, this.offset);
    560 
    561   int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
    562 
    563   int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
    564 }
    565 
    566 class TestPointReader extends TableReader<TestPointImpl> {
    567   const TestPointReader();
    568 
    569   @override
    570   TestPointImpl createObject(BufferContext object, int offset) {
    571     return new TestPointImpl(object, offset);
    572   }
    573 }
    574